Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke a method on a object passed to a mocked method

I am quite new to gmock way of working.

I have a mock with addEvent method which takes object of the type MyClass by a pointer. I need to invoke MyClass::makeCall on this object.

class SchedulerMock
{
public:
    MOCK_CONST_METHOD1(addEvent, void(MyClass*));

};

I found this topic: What is the easiest way to invoke a member function on an argument passed to a mocked function?

And there the example:

IFooable* ifooable = new IFooableImpl(...); 
TMockFoo MockFoo;
ON_CALL(MockFoo, Foo(_))
  .WithArg<0>(Invoke(&ifooable,&IFooable::Fooable));

But I don't want invoke a method on a object I created in test. I want mock to invoke makeCall on object that is actually passed to a mock. So I can inject my mock to another class that will create some new objects, and call addEvent on my schedulerMock and I would like this mock to invoke makeCall on a passed argument everytime someone calls addEvent on my mock. Hopefully I made myself clear.

Is this possible to do?

like image 367
Jarosław Bober Avatar asked Sep 27 '22 05:09

Jarosław Bober


1 Answers

You can define a custom Action (in the namespace scope - outside any other functions, tests, etc.). The Action will have access to the arguments of the mocked function call, which in this case is the MyClass * you want to call makeCall on:

ACTION(MakeCall)
{
    // arg0 is predefined as 0-th argument passed to the mock function call,
    //  MyClass* in this case
    arg0->makeCall();
}

TEST(...)
{
    // Create mock object and set expectation, and specify to invoke the 
    //  MakeCall Action
    SchedulerMock mock;
    EXPECT_CALL(mock, addEvent(_))
        .WillOnce(MakeCall());

    ...
}

When mock.addEvent(my_class_ptr) is called, the MakeCall action will be invoked with the given MyClass * pointer.

You can also use this to pass parameters that are defined in the test to the Action. For example if your MyClass::makeCall method took an int parameter, let's say, and you wanted to pass two different values the first and second time the method is called:

class MyClass
{
    void makeCall(int);
};

ACTION_P(MakeCall, value)
{
    arg0->makeCall(value);
}

TEST(...)
{
    const int FIRST_VAL = 10;
    const int SECOND_VAL = 20;

    MyClass my_class_obj;
    SchedulerMock mock;
    EXPECT_CALL(mock, addEvent(_))
        .WillOnce(MakeCall(FIRST_VAL))
        .WillOnce(MakeCall(SECOND_VAL));
    ...
}

See the Google mock documentation for more details:

Google Mock Cheat Sheet - Defining Actions

Google Mock Cookbook - Writing New Actions Quickly

like image 176
TWReever Avatar answered Sep 30 '22 07:09

TWReever