我正在尝试使用 C 的 FFF 模拟库 (https://github.com/meekrosoft/fff) 对 C 代码进行单元测试。我遇到的问题是 gcc 将我的模拟对象视为原始函数的重新定义,并因此抛出编译器错误。
我创建了 2 个模仿我的用例的测试文件。
my_lib.c
有一些内部函数的定义。 test.c
正在导入 my_lib.c
,因为目的是测试源文件中的所有功能。
//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);
}
我正在编译成这样的目标文件,但这给了我一个立即编译错误:
$ 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)
^
我需要能够从源文件中模拟出函数,同时能够测试遗留源文件,而无需修改任何源文件或头文件。我对 fff 和/或 gcc 缺少什么? 编辑:让我添加这个。我可以从
my_lib.c
中删除 do_thing() 的定义,然后我的编译、模拟和测试完全按照预期工作,因为对 do_thing 的所有调用现在都转到我的模拟对象。我希望能够模拟在测试的源代码中已经定义的函数。
选项 1:
在原始函数定义(在 c 文件中)之前添加
weak
语句。例如,使用 GCC,您可以在函数定义之前编写:
__attribute((weak))
。
之前:void foo(void)
之后:
__attribute((weak)) void foo(void)
这告诉编译器,如果代码中同一函数有另一个定义,则具有
weak
属性的定义将被忽略。
此外,如果您不想更改源代码,可以使用#ifdef UNIT_TEST_ENABLED
添加它,并确保定义 UNIT_TEST_ENABLED 仅在单元测试项目中定义,而不是在生产代码项目中定义。 例如:
#ifdef UNIT_TEST_ENABLED
__attribute((weak))
#endif
void foo(void)
选项2: