I'm trying to use the FFF mocking library for C (https://github.com/meekrosoft/fff) to unit test C code. The issue I'm running into is gcc is seeing my mock object as a redefinition of the original function and throwing compiler errors because of it.
I created 2 testing files that mimick my use cases. my_lib.c
has definitions of some internal functions. test.c
is importing my_lib.c
because the intent is to test all the functions from the source file.
//my_lib.c
int thing = 0;
int get_thing () {
return thing;
}
int do_thing (void) {
return thing;
}
int set_thing (int x) {
thing = x;
return do_thing();
}
//test.c
#include "fff.h"
#include "my_lib.c"
DEFINE_FFF_GLOBALS;
FAKE_VALUE_FUNC0(int, do_thing);
void setup(void)
{
// Reset the FFF call history between tests
FFF_RESET_HISTORY();
// Reset the FFF mock objects between tests
RESET_FAKE(do_thing);
}
void test_do_thing(void)
{
set_thing(11);
ASSERT_EQ(1, do_thing_fake.call_count);
}
void test_nested_mock(void)
{
do_thing_fake.return_val = -2;
int ret = set_thing(11); //set_thing() returns do_thing() which is mocked to return -2
ASSERT_EQ(-2, ret);
}
I'm compiling into an object file like so, but this gives me an immediate compilation error:
$ gcc -g -c test.c -o test.o
In file included from test.c:1:0:
test.c:7:23: error: redefinition of ‘do_thing’
FAKE_VALUE_FUNC0(int, do_thing);
^
fff.h:1632:45: note: in definition of macro ‘DEFINE_FAKE_VALUE_FUNC0’
RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(void){ \
^
test.c:7:1: note: in expansion of macro ‘FAKE_VALUE_FUNC0’
FAKE_VALUE_FUNC0(int, do_thing);
^
In file included from test.c:3:0:
my_lib.c:12:1: note: previous definition of ‘do_thing’ was here
do_thing (void)
^
I need to be able to mock out functions from source files while being able to test legacy source files without modifying any source or header files. What am I missing with fff and/or gcc?
EDIT: Let me add this. I could remove the definition of do_thing() from my_lib.c
and then my compilation, mocks, and tests work exactly as expected because all calls to do_thing now go to my mock object. I want to be able to mock a function that is already defined within the source code under test.