如何在传递给模拟方法的对象上调用方法

时间:2015-11-14 09:39:00

标签: c++ unit-testing googletest googlemock

我对gmock的工作方式很陌生。

我有一个带有addEvent方法的mock,它通过指针获取MyClass类型的对象。我需要在这个对象上调用MyClass :: makeCall。

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

};

我找到了这个话题: What is the easiest way to invoke a member function on an argument passed to a mocked function?

还有例子:

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

但我不想在我在测试中创建的对象上调用方法。我想mock在实际传递给mock的对象上调用makeCall。 所以我可以将我的模拟注入另一个将创建一些新对象的类,并在我的schedulerMock上调用addEvent,我希望每次有人在我的mock上调用addEvent时,这个mock都会在传递的参数上调用makeCall。 希望我能说清楚。

这可能吗?

2 个答案:

答案 0 :(得分:3)

您可以定义自定义Action(在命名空间范围内 - 在任何其他函数,测试等之外)。 Action可以访问模拟函数调用的参数,在这种情况下,您要调用MyClass * makeCall

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());

    ...
}

调用mock.addEvent(my_class_ptr)时,将使用给定的MakeCall指针调用MyClass *操作。

您还可以使用它将测试中定义的参数传递给Action。例如,如果您的MyClass::makeCall方法采用了int参数,那么您可以在第一次和第二次调用该方法时传递两个不同的值:

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));
    ...
}

有关详细信息,请参阅Google模拟文档:

Google Mock Cheat Sheet - Defining Actions

Google Mock Cookbook - Writing New Actions Quickly

答案 1 :(得分:1)

您可以使用另一个调用模拟函数的函数...

class SchedulerMock
{
  public:
    //.... etc
    void addEvent(MyClass* c) const
    {
      c->makeCall();
      mockAddEvent(c); //Wholla, test still works and makeCall called. 
    }

    MOCK_CONST_METHOD1(mockAddEvent, void(MyClass*));
};