Reputation: 1265
Sometimes, we need to do mock test. The most widely used method to do dependency inject is using template or interface.
However, sometimes, for some the legacy code, there exist some concrete class without virtual function and template. For some reason we do not want to or can not to modify the production code. But we still want to do the mock test on the concrete class.
There are already exist lots of discussion about the topic. Most of people said that it is very hard to do that, if not impossible.
Luckily, I seem have found the dawn.
(1) Pavel Minaev's answer in Interfaces vs Templates for dependency injection in C++
With C++, there's another option - you give your mock classes exact same names as the real classes, and when linking your unit tests, just link them with mock object/library files instead of real ones.
(2) sdg's answer in fake/mock nonvirtual C++ methods
One way that we sometimes use is to split the original .cpp file into at least two parts.
Then the test apparatus can supply its own implementations; effectively using the linker to do the dirty work for us.
This is called the "Link Seam" in some circles.
It is in theory yes. we can demonstrate it using a simple case as an example.
A simple program exist two class, A
and B
. B is a user of A.
When we want to do unit test of class B. We can define another A
in MockA.cpp
. and generate unit test execute file via the follow command.
g++ testB.cpp B.cpp MockA.cpp
When it is the time for publish, we can generate executable file via follow command
g++ Main.cpp B.cpp A.cpp
My problem is how can we implement that in a huge program?
It a real program, may be exist a lot of class and they be packed into library.
For example: a huge program need using two library. libA
comes from class A1,A2,A3,...A100
. libB
comes from class B1,B2,B3,....B100
.
Suppose we want do unit test of B3, and we want A1
,A2
,B1
,B2
be mocked. How could we do that?
We need a libA without A1,A2
,libB without B1,B2
, MockA1
, MockA2
, MockB1
, MockB2
?
And further more, if B4
,B5
,B6
all need do something like B3
, it seems very complicated.
Do it manually is complicated, it is very easy to make mistake and hard to maintain.
I do not know how to let linker do the dirty work for us?
Someone in above link said the technique have already been used into practice project. But I search a lot and have not clue.
Any link to opensource project already using this technique will be very helpful. Using CMake or Makefile to compile will even better for me to understand.
Thanks for your time.
Edit
Mike van Dyke share a another method to do the mock without virtual function. The method can make mock works and without using linker. It is a another solution to make mock.
Using googlemock with fake impls of non-virtual functions
Upvotes: 3
Views: 1485
Reputation: 5939
I understand your scenario as follows: For testing B3
you need the real B3
and mocks of A1
, A2
, B1
and B2
. Your assumption is, that you would be using a similar library setup as for the production code: There would be a library with B3
, B4
, B5
, but certainly not with B1
and B2
, since these shall be mocked.
My proposal would be, for the unit test executables, to choose a different library setup: Create individual libraries libMockA1
, libMockA2
etc. and similarly individual libs for the mocked Bx
classes. Then you can combine them more independently when building the test executables. For testing B3
you would then link the B3
object files with libMockA1
, libMockA2
, libMockB1
and libMockB2
. For testing B4
you would link the B4
object files with, for example, libMockA1
, libMockB1
and libMockB3
, etc.
Alternatively, you could give up on using libraries at all for the unit-testing and only link object files individually.
You still would have to create the mocks for the Ax
and Bx
classes, but you can then combine them individually for each test executable - without need to also have differently configured libraries created for each test executable.
Upvotes: 1