C FFF 模拟重定义 [英] C FFF mock redefinition

查看:65
本文介绍了C FFF 模拟重定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 FFF 模拟库用于 C (https://github.com/meekrosoft/fff) 对 C 代码进行单元测试.我遇到的问题是 gcc 将我的模拟对象视为对原始函数的重新定义,并因此引发编译器错误.

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.

我创建了 2 个模拟我的用例的测试文件.my_lib.c 有一些内部函数的定义.test.c 正在导入 my_lib.c,因为目的是测试源文件中的所有函数.

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)
 ^

我需要能够从源文件中模拟出函数,同时能够测试遗留源文件而无需修改任何源文件或头文件.我在 fff 和/或 gcc 中遗漏了什么?

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?

让我添加这个.我可以从 my_lib.c 中删除 do_thing() 的定义,然后我的编译、模拟和测试完全按预期工作,因为所有对 do_thing 的调用现在都转到我的模拟对象.我希望能够模拟已在被测源代码中定义的函数.

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.

推荐答案

所以你的问题的答案取决于你想要模拟的这个函数是否也是你想要测试的函数.

So the answer to your question depends on whether this function that you want to mock is a function you also want to test.

如果您只想在测试中模拟该函数而不使用其原始实现,那么解决方案很简单:

If you only want to mock the function in your tests and not use its original implementation, then the solution is simple:

在原始函数定义之前(在 c 文件中)添加 weak 语句.例如,在 GCC 中,您在函数定义之前编写:__attribute((weak)).之前:

add the weak statement prior to the original function definition (in the c file). For example, with GCC you write: __attribute((weak)) before the function definition. Before:

void foo(void)

之后:

__attribute((weak)) void foo(void)

这告诉编译器,如果代码中有同一个函数的另一个定义,则忽略具有 weak 属性的那个.

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.

此外,如果您不想更改源代码,您可以使用 #ifdef UNIT_TEST_ENABLED 添加它,并确保定义 UNIT_TEST_ENABLED 仅定义在单元测试项目中,而不是在生产代码项目.例如:

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. For example:

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

选项 2:

如果您想在某些测试中使用原始实现但也能够在其他测试中进行模拟,那么我建议您按照我在这里写的说明进行操作:https://stackoverflow.com/a/65814339/4441211

这篇关于C FFF 模拟重定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆