3

I'm trying to understand the idiomatic way to code. I'm using gmock to unit test the components I write. Gmock requires methods to be virtual to be able to mock but the class I'm trying to mock has a non virtual method that I would like to be mocked out.

So the options are to either mark the methods as virtual or create an interface with pure virtual methods. Neither of them seems ideal as I would be doing either of them just to test the code. How is it usually approached in the C++ world?

2
  • 2
    I would argue that making an interface is not 'just to test the code'. Instead, it is ensuring that all your code works against an interface and not a concrete implementation. That is one of the basic principles of a good OO design, and one that comes along naturally when using unittests.
    – JDT
    Commented Apr 7, 2016 at 7:14
  • or, use a #define VITRUAL, whcih expands to eithe virtual or nothing, deponing on #ifdef TESTING
    – Mawg
    Commented Apr 7, 2016 at 11:59

3 Answers 3

4

Your design or test is wrong.

Instead of mocking using a framework, try create your own derived class and design your test around this "mock" class. You will realize that idea of mocking non-virtual methods doesn't make any sense. The idea of virtual methods is that the base class wants some functionality and expects it's children to provide it. If the base class does not make method virtual, it means it doesn't expect it's children to change the behavior of that method. And as such it is integral part of the class and should be tested as such. Mocking out non-virtual method would mean you aren't testing whole behavior of the base class.

One thing that comes to mind, that would "force" you to do this is that the base class has multiple responsibilities and that it should be separated into multiple classes where the non-virtual one is actually API of the extracted class.

2

You usually mark class as virtual when, besides having some sort of implementation (either directly in the class declaring the function itself or in a child inheriting this class), you want the declaration to state a contract, which must be fulfilled by the implementations.

The declaration basically says: If you give me this set of parameters of these types, I am guaranteed to return this type of a variable (the return type). You do not need to care what happens inside the function itself, but you can be pretty sure these if you give me some parameters of these types, you can be pretty sure I'll give you the return type back.

This is called abstraction, when the pivots of your application are the declarations providing expected but not exact behaviours. Interfaces, or in C++ classes containing nothing but pure virtual methods, are exactly that. They define a contract but don't provide the implementation.

If you want to unit test, what you want in your code is to depend on nothing but virtual functions. You can do that by either defining a function of a class already providing behaviour as virtual or extracting the function's declaration to a whole new class representing the interface of the function (making the declaration pure virtual), have the initial class inherit from this newly created abstract class and then use this newly created abstract class throughout your project.

1

You could use static inheritance, and inject the object through the template argument. Then in the unit tests, inject the mock object, instead of the real object.

Something like this :

struct A {
  void doThings() {
  }
};

struct MockA {
  MOCK_METHOD0(doThings, void());
};


template< typename doer >
struct B {
  void foo() {
    a.doThings();
  }

  doer a;
};

Then in your application, use real class :

B< A > b;

and in unit tests the mock :

B< MockA > b;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.