Can googlemock mock method calls from within other

2019-05-21 19:41发布

问题:

Is it possible to mock method calls from within other method calls of the same class? I am new to C++ (primarily a C developer) and very new to googlemock and Google Test so forgive me if this is answered elsewhere and I didn't understand the answer! Below is a simple example that should explain what I want to do. Using the example below, I want to mock ReturnInput, while testing ReturnInputPlus1.

using ::testing::Invoke;
using ::testing::_;
using ::testing::Return;

class MyClass
{
public:
    MyClass() : x(1) {}
    virtual ~MyClass() {}

    int ReturnInput(int x) { return x; }
    int ReturnInputPlus1(int x) { return ReturnInput(x) + 1; }
};

class MockMyClass : public MyClass
{
public:
    MockMyClass()
    {
        ON_CALL(*this, ReturnInput(_)).WillByDefault(Invoke(&real, &MyClass::ReturnInput));
        ON_CALL(*this, ReturnInputPlus1(_)).WillByDefault(Invoke(&real, &MyClass::ReturnInputPlus1));
    }
    virtual ~MockMyClass() {}

    MOCK_METHOD1(ReturnInput, int(int y));
    MOCK_METHOD1(ReturnInputPlus1, int(int));

private:
    MyClass real;
};

TEST(MyClassTest, mockUseClassMethod)
{
    MockMyClass mock;

    EXPECT_CALL(mock, ReturnInput(_))
        .WillOnce(Return(2));
    EXPECT_CALL(mock, ReturnInputPlus1(_))
        .Times(1);

    EXPECT_EQ(3, mock.ReturnInputPlus1(1));
}

When I run the above test, I would expect all the tests to succeed. Instead I get the following output:

1>[ RUN      ] MyClassTest.mockUseClassMethod
1>.\MyClassTest.cpp(15): error: Value of: mock.ReturnInputPlus1(1)
1>  Actual: 2
1>Expected: 3
1>.\DllInfoTest.cpp(10): error: Actual function call count doesn't match EXPECT_CALL(mock, ReturnInput(_))...
1>         Expected: to be called once
1>           Actual: never called - unsatisfied and active

回答1:

Your call to MockMyClass::ReturnInputPlus1(1) calls MyClass::ReturnInputPlus1(1) on real by default, which calls MyClass::ReturnInput(2). The object that ReturnInputPlus1() is running on is not mock, it's mock.real, and when it calls ReturnInput() it calls the original version of the function. What you want to do is create a MockMyClass that has a mock override of ReturnInput() but doesn't mock out ReturnInputPlus1() at all -- you don't want to have both a mock version of your class and a real version that it sometimes delegates to.