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:
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.