Mocking non-virtual member functions with gmock
23 / 05 / 2021

tldr;

Recently I have encountered a problem. I have managed to solve it using pretty simple and kinda obvious solution, but all I have had found online was way too complicated - so here I am sharing it.. For unit testing in this project we are using gtest and gmock. I don't know gmock that well tbh, so I started searching web. I wanted to mock one of the classes so I can test other, dependent classes so they can be tested *duh*. Normally u just provide a class that inherits from the class u want to mock and overwrite implementation of function with MOCK_METHOD macro. The problem is that, the function I want to mock is not virtual. Documentation of gmock says:

Making a non-virtual function virtual is a big decision. It creates an extension point where subclasses can tweak your class' behavior. This weakens your control on the class because now it‘s harder to maintain the class’ invariants. You should make a function virtual only when there is a valid reason for a subclass to override it.

I agree that making function virtual only to make it testable is simply poor engineering. Especially in project I was working in - we do some rather limited embedded project - any virtual call that is not necesary is not welcome and it is also against "You don't pay for what you don't use" thing. TBH I was surprised that gmock was not acheving mocking with intercepting calls to mocked functions on the linker level. One could easily mock any (free, member virtual, member non-virtual) functions without much problems (there actually might be some tiny problems with this aproach, I haven't really think about it that much). Anyway - gmock is not using linker level mocking and requires user to make their class a template and injecting the implementation as dependency. If u are not familiar, you can read more about that here under "Mocking Nonvirtual Methods" section. This is horrible - it changes how I use my production code - I have not liked it!

Solution

There is another, simple solution. It makes the functions "conditionaly virtual". They are virtual when we are testing - only for purpose of mocking, but in production they are simple, non-virtual functions. So we only pay the overhead of virtual function when we are testing - which is not ideal but is not terrible either.
Let's say that we have a class we want to mock:

class IWantToBeMocked
{
public:
        int setNumber(int n);
        void resetNumber();

private:
        int n;
};
          

To make it "conditionally virtual" we split the interface into 3 parts and the middle one will be "conditionally virtual". Here's how:

#if defined(UNITTEST)
#define TEST_IFACE virtual
#else
#define TEST_IFACE
#endif

class IWantToBeMocked
{
private:
        void setNumberImpl(int n);
        int resetNumberImpl();

protected:
        void TEST_IFACE setNumberIface(int n)
        {
                setNumberImpl(n);
        }

        int TEST_IFACE resetNumberIface()
        {
                return resetNumberImpl();
        }

public:
        void setNumber(int n)
        {
                setNumberIface(n);
        }

        int resetNumber()
        {
                return resetNumberIface();
        }

private:
        int n;
};
          

Functions are one liners so the compilers will most likely inline them (if you want to be 100% sure u can use __attribute__((always_inline)) for GCC or smth). And when we are unit testing the functions would be virtual and thus can be easily mocked with MOCK_METHOD macro.