Passing arbitrary arguments to invocked methods with Google C++ Mocking Framework (Google Mock) (V1.5)

SylvainD picture SylvainD · Jan 15, 2015 · Viewed 13.1k times · Source

I have a mock method. When it is called, I'd like it to call another function before calling its normal behavior. Something like :

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        Invoke(my_obj, &SomeAdditionalMethodIWantToCall),
        Invoke(my_obj, &DefaultBehavior),
        ));

The only problem is that SomeAdditionalMethodIWantToCall expects parameter that not at all related to the one provided to MockedMethod. I'd like to be able to give them but I am struggling with the syntax. I wish there was something like (in fake syntax) :

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        Invoke(my_obj, &SomeAdditionalMethodIWantToCall, arg1, arg2, arg3),
        Invoke(my_obj, &DefaultBehavior),
        ));

I have looked for such a thing in the documentation without any success.

In Using a Function or a Functor as an Action, we have :

  • Invoke(f), Invoke(object_pointer, &class::method), InvokeWithoutArgs(f), InvokeWithoutArgs(object_pointer, &class::method) which will just forward (or not) the parameter provided to the mocked function when it is called.

  • InvokeArgument<N>(arg1, arg2, ..., argk) seems to be for calling one of the parameter.

In Composite Actions

  • WithArg<N>(a) and WithArgs<N1, N2, ..., Nk>(a) seem to be to select which parameters from the original function get forwarded.

I guess I am missing something quite obvious but I am a bit stuck here so any suggestion will help.

Answer

RA. picture RA. · Jan 18, 2015

One possible option would be to save the values of the arguments to class variables using the Assign action and then invoke the other function using a helper. Use the following expectation:

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        Assign(&classVariable1, arg1),
        Assign(&classVariable2, arg2),
        Assign(&classVariable3, arg3),
        InvokeWithoutArgs(my_obj, &MyClass::SomeAdditionalMethodIWantToCallHelper),
        Invoke(my_obj, &MyClass::DefaultBehavior),
        ));

Then define your helper function as follows:

void MyClass::SomeAdditionalMethodIWantToCallHelper()
{
    SomeAdditionalMethodIWantToCall(classVariable1, classVariable2, classVariable3);
}

Edit

Another possible option is to write a custom action that takes in a pointer to a member function along with the arguments you wish to pass to it. This is closer to what you originally desired for syntax. Here is the custom action:

ACTION_P5(InvokeUnrelatedFunction, classPointer, pointerToMemberFunc,
          first, second, third)
{
    (classPointer->*pointerToMemberFunc)(first, second, third);
}

Here's how you would use it in an expectation:

EXPECT_CALL(*my_obj, MockedMethod(_,_,_,_,_,_))
    .WillOnce(DoAll(
        InvokeUnrelatedFunction(my_obj, &MyClass::SomeAdditionalMethodIWantToCall,
                                arg1, arg2, arg3),
        Invoke(my_obj, &MyClass::DefaultBehavior),
        ));