We have a legacy code base in entirely C++. Our build system is CMake. My first stab at unit testing was as follows:
- Define a target (
LibraryA
). This library contains the code to test. - Define a unit test target per CPP test file in
LibraryA
being tested and link againstLibraryA.lib
.
Basically the source structure is like so:
LibraryA/
Source/
Utils/
MyClass.cpp
MyClass.hpp
AnotherClass.cpp
AnotherClass.hpp
Network/
Socket.cpp
Socket.hpp
Tests/
Utils/
TestMyClass.cpp
TestAnotherClass.cpp
What we have here is a mirror structure of the Source
directory inside Tests
. This structure allows me to use include order trickery at the compiler command line level to prioritize where class headers are found for mocking purposes. Each Test*.cpp
file under Tests
results in 1 executable. So 1 executable test per class being tested.
The issue is that I'm linking against LibraryA.lib
in my test executable. This results in ODR violation because if I want to mock the Socket class, the LibraryA.lib
will have already compiled symbols into it. Now I can't mock it without duplicating symbols and the linker will complain.
Overall setting up unit test structure has been a giant pain from the build system perspective when it comes to mocking.
Is there a good solution to this problem? Is my approach to test structure completely wrong?
Best Answer
There are two options :
The link time dependency injection (the first option), means that you inject the code during the linking time.
If Socket.h declares the Socker class, and Socket.cpp implements it, then add a header defining the mock class with the same name - Socket. It has to be in the same namespace as original Socket.
Then when you build the unit test, do not compile and link the Socket.cpp, you need to compile and link the mock class, and use it in the unit tests.