0

I have a scenario where my coworker is writing functions that I wish to use in my module. He wrote the unit tests for his module, and I am writing the unit tests for mine. Naturally I would like to mock his functions for my test.

The production code is written in C and compiled as a library separately from the Unit test code. At link time, we are overwriting the object code of the production for the Mock version. However this overwrites ALL calls to that particular function instead of just in my unit tests.

Here is an example.

Using CPPUTEST, I have MockSupport_c.h at my disposal. So I write up a mock for his function. Ex

real function:

int read_bytes(int count)
{
    // for loop read the bytes
    return success;
}

I call the above with my function that I want to test

int read()
{
    return read_bytes(256);
}

The test module looks something like the following:


// create the mock
int read_bytes(int count)
{
    mock_c()->actualCall("read_bytes");
    return 1;
}

// test the code
TEST(group, test_name)
{
    mock_c()->expectOneCall("read_bytes");
    read();
    mock_c()->checkExpectations();
}

When the unit test is compiled, the linker will replace the production code implementation with the mocked version; but it will do it for all calls to that function. So my coworkers unit tests now call mocks, when it should be testing his actual calls.

How do I get the mocks to only apply during my tests, and not overwrite my coworkers calls?

Or am I just way off base with how all of this works?

  • How do you compile and link? Why can't you link each test with the appropriate real or mock modules? – the busybee Dec 10 '20 at 11:55
  • After compilation, the result is 1 single executable that will exercise all tests. With the production code being compiled as a library, and the mocks either in their own library or in the main execution; the linker (by design) will link the call to the first function that matches said call. So if I put the mocks first on the command line, the linker will fill **all** calls to that mock, then load the production library and fill in the rest... and if I put the production library first on the command line, then the linker will link all function calls to the real code and non to the mocks. – Alex Schultz Dec 10 '20 at 14:05
  • I am using the Visual Studio vc++ compiler tool chain. In my reading, I have discovered no way to specify to the linker which functions get switched out and which functions dont. If there is a way to do that, then I would really like to know. I am sure that would solve the issue. – Alex Schultz Dec 10 '20 at 14:07
  • Oh, wow. Is this a requirement of your development process, or of CppUTest? I'm really sure that the unit testing framework provides some ideas how to handle this. -- However, if you _must_ create a single executable, you might consider to use some preprocessor magic to let the compiler differentiate the use cases (real/mock). – the busybee Dec 10 '20 at 14:33
  • There are no set requirements for how the unit-testing frame work is implemented, only that we do it. So I have some flexibility. I have chosen to do link-time substitution because I find it to be the cleanest solution for switching out functions without modifying the production code base. Littering our code with `#ifdef` is not something that the team is fond of. Having multiple executables is an acceptable solution, so long as their management is an easy, automated, solution. This is something I have not thoroughly looked into; so more information is welcome. – Alex Schultz Dec 10 '20 at 14:54
  • I never used CppUTest, so my experience is mainly limited to a (closed-source) in-house framework for C, which was derived from MinUnit, and GoogleTest. However, current frameworks should work in similar manners. -- I always found it the most simple solution to create an executable for each test suite (or even test case), and have as many executables as seen fit. With a Makefile this leads to quick development cycles, as only changed (that is: worked-on) tests will be compiled, linked, and run. Use Make variables to list all executables, and so on. – the busybee Dec 10 '20 at 15:44
  • okay, it certainly seems like that might be my best solution. I also found the same question being asked over on the TDD stackexchange and it seems that your recommendation is the same as theirs. https://softwareengineering.stackexchange.com/questions/163360/test-driven-development-with-plain-c-manage-multiple-modules I will play around with it and report back. Thank you. – Alex Schultz Dec 10 '20 at 15:50

0 Answers0