Xu Hui
Xu Hui

Reputation: 1265

How to do mock test via linker in C++

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

Answers (1)

Dirk Herrmann
Dirk Herrmann

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

Related Questions