Codoscope
Codoscope

Reputation: 944

Google-Mock an already declared method

The syntax of MOCK_METHOD can be used inside a class definition:

class A {
    MOCK_METHOD0(f, void(void));
};

Is it possible to mock a method that has already been declared? What I want is to do something similar to:

#include "gmock/gmock.h"

class HelloTest {
    void f();
};

MOCK_METHOD0(HelloTest::f, void(void));

The idea is to put the class definition in an hpp file and then the mocks in a cpp file. In effect, my class definition with its methods' prototypes needs to be in common with other cpp files in my build chain and I don't want to use virtual functions.

Unfortunately, when I try to do what I wrote above, I get the following error on the line that contains MOCK_METHOD0:

error: ‘gmock0_HelloTest’ has not been declared

What does this error mean and is there a way to do what I want?

Upvotes: 1

Views: 1395

Answers (1)

frslm
frslm

Reputation: 2978

To begin with, your MOCK_METHOD0() declaration must belong to a mock class, under a public section. For instance, your code snippet:

#include "gmock/gmock.h"

class HelloTest {
    void f();
};

MOCK_METHOD0(HelloTest::f, void(void));

Should instead look like this:

#include "gmock/gmock.h"

class HelloTest {
    virtual void f();
};

class Mock_HelloTest : public HelloTest {
public:
    MOCK_METHOD0(f, void(void));
};

Now, you'll notice that I've changed f() to be virtual instead, since your use of HelloTest::f in MOCK_METHOD0 requires f() to be virtual.

Since you don't want to use virtual functions, your only other option is to use what the Google Mock team calls hi-perf dependency injection. With this non-virtual approach, you'd have to create a separate mock class that doesn't inherit from HelloTest. You'd also need to templatize any code that currently uses HelloTest to switch between HelloTest in production and Mock_HelloTest in tests.

As an example, let's say you have the following function that calls HelloTest::f():

void RunHelloTest() {
    HelloTest HT;
    HT.f();
}

You would set up your code snippet as follows:

#include "gmock/gmock.h"

class HelloTest {
    void f(); // <- f is no longer virtual
};

class Mock_HelloTest { // <- Mock_HelloTest no longer inherits from HelloTest
public:
    MOCK_METHOD0(f, void(void));
};

And modify RunHelloTest() to accept a template type argument:

template <class HelloTestClass>
void RunHelloTest() {
    HelloTestClass HT;
    HT.f(); // <- will call HelloTest::f() or Mock_HelloTest::f()
}

With this setup, you'd call RunHelloTest<HelloTest>() in your production code, and RunHelloTest<Mock_HelloTest>() in your test code.

Upvotes: 1

Related Questions