Search code examples
c++unit-testinggoogletestgooglemock

Adding expected calls in a loop


This is what I want to achieve. In my test fixture I want to call a helper functions with a parameter n to tell the test fixture how many initialization sequences should be expected. Some parameters used in the sequences are stored in three std::vector containers; fileDescriptor, handle, selectionObject.

What I have written is this:

void MyTest::init_Ok(uint32_t n)
{
  for (uint32_t i = 0; i < n; ++i)
  {
    fileDescriptor.push_back(i); // FDs starting at 0
    handle.push_back(reinterpret_cast<void*>(18 + i)); // handles starting at 18
    selectionObject.push_back(555 + i); // SOs starting at 555

    EXPECT_CALL(MyMockApi::getApi(), initialize(Pointee(nullptr), StrEq("InitString"), MyMatcher()))
      .WillOnce(DoAll(SetArgPointee<0>(handle[i]),
                      Return(INIT_OK)));
    EXPECT_CALL(MyMockApi::getApi(), selectionObjectGet(handle[i], Pointee(nullptr)))
      .WillOnce(DoAll(SetArgPointee<1>(selectionObject[i]),
                      Return(SELECTION_OK)));
    EXPECT_CALL(MyMockApi::getApi(), finalize(handle[i]))
      .WillOnce(Return(FINAL_OK));
  }
}

I know why it's not working. It is expected that all calls to initialize will be identical but yet I want to perform different actions (parameter depending on loop counter i) for the first, second, third, ..., nth call. The current implementation will only expect one call to initialize no matter parameter n. Is it possible to fix this and keep it a loop somehow, or do I have to add the actions with a WillOnce line for each i? This would mean i have to check n and add different number of WillOnce lines for different possible values of n, which i really want to avoid.


Solution

  • One way could be to use Invoke. You can write a function which will have access to the handles container and a running member/static variable(lets say counterVar) which will indicate the number of times the function is hit. Based on the value of counterVar, you can decide the logic.

    .WillRepeatedly(Invoke(<your function>))
    

    Something like:

    EXPECT_CALL(MyMockApi::getApi(), initialize(Pointee(nullptr), StrEq("InitString"), MyMatcher()))
          .WillRepeatedly(Invoke(successfulInitialize));
    
    ReturnCode successfulInitialize(void* op, std::string msg)
    {
       static int counterVar = 0;
       *op = handles[counterVar++];
       return INIT_OK;
    }