Search code examples
c++googletestgooglemock

gmock: Why isn't EXPECT_CALL detecting the function call in my test?


The text "callback called" from Callback() prints to console, but gmock fails the test saying that no callback happened. What am I doing wrong?

class MyClass
{
    public:
        MyClass() { };
        virtual ~MyClass() { };
        void Callback() { printf("callback called\n"); };
};

class MyClassMock : public MyClass
{
public:
    MOCK_METHOD0(Callback, void());
};

class Caller
{
public:
    Caller(MyClass *myClass) { m_myClass = *myClass; };
    void Call() { m_myClass.Callback(); };
private:
    MyClass m_myClass;
};

TEST(BasicTest, Positive)
{
    MyClassMock mock;
    EXPECT_CALL(mock, Callback()).Times(1);

    Caller caller(&mock);
    caller.Call();
}

Solution

  • Your

    void Callback();
    

    method is not declared virtual. So you can't mock it that way with a simple derived mock class.

    To cite from the google-mock documentation

    Google Mock can mock non-virtual functions to be used in what we call hi-perf dependency injection.

    In this case, instead of sharing a common base class with the real class, your mock class will be unrelated to the real class, but contain methods with the same signatures.

    The consequence is you have to realize this with a template. There's a concise example given at the documentation section linked from above.


    Trying to "translate" their sample to your case, it should look like

    class MyClass {
        public:
            MyClass() { };
            virtual ~MyClass() { };
            void Callback() { printf("callback called\n"); };
    };
    
    class MyClassMock {
    public:
        MOCK_METHOD0(Callback, void());
    };
    
    template<class T>
    class Caller {
    public:
        Caller(T& myClass) : m_myClass(myClass) {}
        void Call() { m_myClass.Callback(); }
    private:
        T& m_myClass;
    };
    
    TEST(BasicTest, Positive) {
        MyClassMock mock;
        EXPECT_CALL(mock, Callback()).Times(1);
    
        Caller<MyClassMock> caller(mock);
        caller.Call();
    }