Omegastick
Omegastick

Reputation: 1911

Avoid calling base class with Google Mock

I'm trying to mock a class provided by a library. The class has a very costly constructor (it takes ~30 seconds to run) that I'd like to avoid calling. None of the actual class functionality needs to work, I only need a mock object I can use to see if the right methods were called.

class MockClass : public BaseClass
{
  public:
    MockClass();

    MOCK_CONST_METHOD1(methodA, void(const typeA a));
    MOCK_CONST_METHOD1(methodB, void(int b));
    MOCK_CONST_METHOD3(methodC, bool(double c, double d, int e));
};

I'd like something like the above setup, but it still tries to call the default constructor.

How can I get around this?

Upvotes: 3

Views: 2031

Answers (2)

Omegastick
Omegastick

Reputation: 1911

I ended up templatizing the class to be tested, as described here. Using one template instantiation for the tests and one for production.

template <class Class>
class ClassToBeTested
{
  public:
    method(std::shared_ptr<Class> foo)
    {
        foo->do_something();
    }
}

Then, in the test:

TEST(test_case, test_name)
{
    ClassToBeTested<MockClass> bar;
}

And in the production code:

int main(int argc, char *argv[])
{
    ClassToBeTested<BaseClass> bar;
}

Upvotes: 0

k.v.
k.v.

Reputation: 1223

To construct MockClass object - one of BaseClass constructors should be called anyway.

If BaseClass has another (user-defined) constructor which is acceptable for mock scenario - call it explicitly:

class MockClass : public BaseClass
{
  public:
    MockClass() : BaseClass(/* c-tor args */) {}

    // ...
};

If no such constructor - you will need to add it (can make it protected not to be accessible in regular BaseClass usage context). [edit: since it's a library class - adding constructor is most probably not an option]

Another possible direction would be to introduce pure interface class for BaseClass and mock it instead of mocking BaseClass directly. In this case usage of BaseClass should be switch to new interface usage, and interface implementation will wrap BaseClass and forward required methods call to internal BaseClass object. Thus no extra BaseClass constructors for testing purposes need to be added.

Upvotes: 3

Related Questions