Functions calling order in unit tests in C++

Welcome to the next pikoTutorial ! To ensure a certain order of function calls, GTest provides 2 ways to do that: InSequence object Sequence object ## InSequence object The simplest way to expect specific function call order is to create a InSequence object in dedicated scope: #include #include using namespace ::testing; struct SomeInterface { virtual ~SomeInterface() = default; virtual void FirstMethod() = 0; virtual void SecondMethod() = 0; virtual void ThirdMethod() = 0; virtual void FourthMethod() = 0; }; struct SomeMock : public SomeInterface { MOCK_METHOD(void, FirstMethod, (), (override)); MOCK_METHOD(void, SecondMethod, (), (override)); MOCK_METHOD(void, ThirdMethod, (), (override)); MOCK_METHOD(void, FourthMethod, (), (override)); }; void SomeFunctionToTest(SomeInterface &obj) { obj.FirstMethod(); obj.SecondMethod(); obj.ThirdMethod(); obj.FourthMethod(); } TEST(TestSomeFunction, CallingOrderIsCorrect) { SomeMock obj; { // in this scope the call order matters... InSequence seq; EXPECT_CALL(obj, FirstMethod); EXPECT_CALL(obj, SecondMethod); } // ...and outside of the scope it doesn't EXPECT_CALL(obj, FourthMethod); EXPECT_CALL(obj, ThirdMethod); SomeFunctionToTest(obj); } Sequence object To gain some flexibility, you can create a dedicated Sequence object which then can be passed when calling EXPECT_CALL macro or to any other function as an input argument: TEST(TestSomeFunction, CallingOrderIsCorrect) { SomeMock obj; Sequence seq; // these functions must be called in order... EXPECT_CALL(obj, FirstMethod).InSequence(seq); EXPECT_CALL(obj, SecondMethod).InSequence(seq); // ...and these not necessarly EXPECT_CALL(obj, FourthMethod); EXPECT_CALL(obj, ThirdMethod); SomeFunctionToTest(obj); }

Feb 25, 2025 - 10:39
 0
Functions calling order in unit tests in C++

Welcome to the next pikoTutorial !

To ensure a certain order of function calls, GTest provides 2 ways to do that:

  • InSequence object
  • Sequence object

## InSequence object

The simplest way to expect specific function call order is to create a InSequence object in dedicated scope:

#include 
#include 

using namespace ::testing;

struct SomeInterface
{
    virtual ~SomeInterface() = default;

    virtual void FirstMethod() = 0;
    virtual void SecondMethod() = 0;
    virtual void ThirdMethod() = 0;
    virtual void FourthMethod() = 0;
};

struct SomeMock : public SomeInterface
{
    MOCK_METHOD(void, FirstMethod, (), (override));
    MOCK_METHOD(void, SecondMethod, (), (override));
    MOCK_METHOD(void, ThirdMethod, (), (override));
    MOCK_METHOD(void, FourthMethod, (), (override));
};

void SomeFunctionToTest(SomeInterface &obj)
{
    obj.FirstMethod();
    obj.SecondMethod();
    obj.ThirdMethod();
    obj.FourthMethod();
}

TEST(TestSomeFunction, CallingOrderIsCorrect)
{
    SomeMock obj;

    {
        // in this scope the call order matters...
        InSequence seq;

        EXPECT_CALL(obj, FirstMethod);
        EXPECT_CALL(obj, SecondMethod);
    }

    // ...and outside of the scope it doesn't
    EXPECT_CALL(obj, FourthMethod);
    EXPECT_CALL(obj, ThirdMethod);

    SomeFunctionToTest(obj);
}

Sequence object

To gain some flexibility, you can create a dedicated Sequence object which then can be passed when calling EXPECT_CALL macro or to any other function as an input argument:

TEST(TestSomeFunction, CallingOrderIsCorrect)
{
    SomeMock obj;
    Sequence seq;

    // these functions must be called in order...
    EXPECT_CALL(obj, FirstMethod).InSequence(seq);
    EXPECT_CALL(obj, SecondMethod).InSequence(seq);

    // ...and these not necessarly
    EXPECT_CALL(obj, FourthMethod);
    EXPECT_CALL(obj, ThirdMethod);

    SomeFunctionToTest(obj);
}