Gilson PJ
Gilson PJ

Reputation: 3600

gmock gtest how to setup the mock

Please consider the below code sample

NodeInterface * pPreNode = NULL;
NodeInterface * pChild = NULL;

for (uint16_t Index = 0; Index < Children.size(); ++Index)
{
    pChild = Children[Index];
    if (pPreNode == NULL)
    {
        pChild->SetPrevious(pChild);
        pChild->SetNext(pChild);
    }
    else
    {
        pChild->SetNext(pPreNode->GetNext());
        pChild->SetPrevious(pPreNode);
        pPreNode->GetNext()->SetPrevious(pChild);
        pPreNode->SetNext(pChild);
    }
    pPreNode = pChild;
}

To test this lines how to setup the mock exactly? Children is a vector of Nodes and we are passing Mocked objects.

EXPECT_CALL(Obj, GetNode()).WillOnce(Invoke(this, &GetANewNode));

and the GetANewNode will provide new MockedNode

MockedNode * GetANewNode()
{
    MockedNode * pMockedNode = new MockedNode();
    return pMockedNode;
}

How to provide exact nodes for each Next(), Previous() calls?

EXPECT_CALL(*pMockedNode, SetNext(_));
EXPECT_CALL(*pMockedNode, SetPrevious(_));
EXPECT_CALL(*pMockedNode, GetNext());
EXPECT_CALL(*pMockedNode, GetPrevious());

Upvotes: 3

Views: 1732

Answers (1)

PiotrNycz
PiotrNycz

Reputation: 24430

Simple solution is to have all mocked nodes predefined before test case. And use Sequence/InSequence to be sure that everything happens in proper order.

class ObjTest : public ::testing::Test
{
protected:
   const std::size_t N = ...; // I do not know how many do you need
   std::vector<MockedNode> mockedNode;
   std::vector<Node*> children; 
   Sequence s;
   .... Obj; // I am not sure what is Obj in your question
   ObjTest () : mockedNode(N)
   {}
   void SetUp() override
   {
       // initial setup
       EXPECT_CALL(Obj, GetNode()).WillOnce(Return(&mockedNode.front())).InSequence(s);
   }
};

Having such test class with initial setup - you can create test cases testing various scenarios that happen after initial sequence:

TEST_F(ObjTest, shouldLinkOneNodeToItself)
{
    std::vector<Node*> children { &mockedNode[0] };
    EXPECT_CALL(mockedNode[0], SetNext(&mockedNode[0])).InSequence(s);
    EXPECT_CALL(mockedNode[0], SetPrevious(&mockedNode[0])).InSequence(s);
    Obj.testedFunction(children); // you have not provided your tested function name...
}

And very similar test case for two children:

TEST_F(ObjTest, shouldLinkTwoNodesToEachOther)
{
    std::vector<Node*> children { &mockedNode[0], &&mockedNode[1] };
    // first interation
    EXPECT_CALL(mockedNode[0], SetNext(&mockedNode[0])).InSequence(s);
    EXPECT_CALL(mockedNode[0], SetPrevious(&mockedNode[0])).InSequence(s);
    // second iteration
    EXPECT_CALL(mockedNode[0], GetNext()).WillOnce(Return(&mockedNode[0])).InSequence(s);
    EXPECT_CALL(mockedNode[1], SetNext(&mockedNode[0])).InSequence(s);
    EXPECT_CALL(mockedNode[1], SetPrevious(&mockedNode[0])).InSequence(s);
    // etc...

    Obj.testedFunction(children);
}

Upvotes: 2

Related Questions