2

I have an Embedded C/C++ project and I want to write unit tests for it with CppUTest. One simple test that I want to do is to ensure that a particular C function is called during the test.

Let's say I have two C functions defined in function.h:

void success(void)
{
    // ... Do Something on success
}

void bid_process(void)
{
    bool happy = false;
    // ... processing modifiying 'happy' and setting it to 'true'

    if (happy)
        success(); // Call to success
}

I want to test the function big_process and I want my test to fail if success is not called.

For this purpose I wrote some CppUTests in a separate test file test.cpp:

#include <CppUTest/CommandLineTestRunner.h>
#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

#ifdef __cplusplus
extern "C"
{
    #include "function.h"
}
#endif
TEST_GROUP(TestGroup)
{
    void teardown()
    {
        mock().clear();
    }
};


TEST(TestGroup, Test_big_process)
{
    mock().expectOneCall("success"); // success should be called by the call to big process
    big_process();
    mock().checkExpectations();
}

I checked manually that big_process is working fine and is calling success but now I want my test to do it. But the test fails and tells me:

 Mock Failure: Expected call did not happen.
    EXPECTED calls that did NOT happen:
        success -> no parameters

So my question is simple: how to ensure that success is called during big_process ?

Pierre Baret
  • 1,773
  • 2
  • 17
  • 35

3 Answers3

2

I believe that the mocking support in CppUTest is invasive, i.e. you need to add mocking support to your production code as well. Example:

void success(void)
{
    mock().actualCall("success");
    ....
}

For non-invasive unit testing of plain C code you could instead use e.g. preprocessor or link seams. Check out Michael Feathers' great book Working Effectively with Legacy Code for details.

Actually, an extract from that book covering those seam types can be found here. I'd still recommend any C programmer to read that book - it's invaluable.

rjnilsson
  • 2,343
  • 15
  • 20
2

You are correctly setting the mock expectations but not wiring the mock to the success() function.

This explains a similar issue: https://github.com/cpputest/cpputest/issues/1054

teroi
  • 1,087
  • 10
  • 19
  • Thanks for the link, but I don't get how to wire to the real succes function. – Pierre Baret Oct 09 '18 at 15:13
  • Basically you need to have your own mock function (a test double!) with the same signature (return value, name and argument types of the function) as your actual implementation func and link in the mocked inplementation when building your test executable, with the extern "C" declaration as CppUTest is in fact in C++ and your unit under test is in C. – teroi Oct 09 '18 at 15:21
  • but in fact you can't play this with linker because the success() function is in the same file as the tested function! So, no, you can't really test it this way with any framework! Also consider that you are unit testing and that should be done against the public interface and external dependencies. Unit testing the internal implementation details shouldn't be done and in fact, that is quite difficult when your language of choice is C. – teroi Oct 10 '18 at 11:10
0

Instead of cpputest mock library you could maybe use another mocking framework like for example fake function framework. See https://github.com/meekrosoft/fff/blob/master/README.md

This allows you to write lightweight stub functions that may substitute the actual implementation with a test double. This may be done at linking phase. Link the fff inplementation before the actual implementation so that linker pulls the faked implementation.

teroi
  • 1,087
  • 10
  • 19