简体   繁体   English

C FFF 模拟重定义

[英]C FFF mock redefinition

I'm trying to use the FFF mocking library for C ( https://github.com/meekrosoft/fff ) to unit test C code.我正在尝试使用 C 的 FFF 模拟库( https://github.com/meekrosoft/fff )来对 C 代码进行单元测试。 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.我遇到的问题是 gcc 将我的模拟对象视为对原始函数的重新定义,并因此引发编译器错误。

I created 2 testing files that mimick my use cases.我创建了 2 个模拟我的用例的测试文件。 my_lib.c has definitions of some internal functions. my_lib.c有一些内部函数的定义。 test.c is importing my_lib.c because the intent is to test all the functions from the source file. 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);
}

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?我在 fff 和/或 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.我可以从my_lib.c删除 do_thing() 的定义,然后我的编译、模拟和测试完全按预期工作,因为所有对 do_thing 的调用现在都转到我的模拟对象。 I want to be able to mock a function that is already defined within the source code under test.我希望能够模拟已在被测源代码中定义的函数。

So the answer to your question depends on whether this function that you want to mock is a function you also want to test.所以你的问题的答案取决于你想要模拟的这个函数是否也是你想要测试的函数。

Option 1:选项1:

If you only want to mock the function in your tests and not use its original implementation, then the solution is simple:如果您只想在测试中模拟该函数而不使用其原始实现,那么解决方案很简单:

add the weak statement prior to the original function definition (in the c file).在原始函数定义之前添加weak语句(在 c 文件中)。 For example, with GCC you write: __attribute((weak)) before the function definition.例如,使用 GCC,您可以在函数定义之前编写: __attribute((weak)) Before:前:

void foo(void)

After:后:

__attribute((weak)) void foo(void)

This tells the compiler that if there is another definition for the same function in the code, then the one with the weak attribute is ignored.这告诉编译器,如果代码中有同一个函数的另一个定义,则忽略具有weak属性的那个。

In addition, if you don't want to change the source code you can add it in with #ifdef UNIT_TEST_ENABLED and make sure that the definition UNIT_TEST_ENABLED is defined only the unit test project and not in the production code project.此外,如果您不想更改源代码,您可以使用#ifdef UNIT_TEST_ENABLED添加它,并确保定义 UNIT_TEST_ENABLED 仅定义在单元测试项目中,而不是在生产代码项目中。 For example:例如:

#ifdef UNIT_TEST_ENABLED 
__attribute((weak)) 
#endif 
void foo(void)

Option 2:选项 2:

If you want to use the original implementation in some of the tests but also be able to mock in other tests then I suggest you follow the instructions I wrote here: https://stackoverflow.com/a/65814339/4441211如果您想在某些测试中使用原始实现但也能够在其他测试中进行模拟,那么我建议您按照我在这里写的说明进行操作: https : //stackoverflow.com/a/65814339/4441211

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM