C 单元测试:存根常量结构 (gcc --wrap)

C Unit Test: stub a constant structure (gcc --wrap)

大家好这是我的具体案例:

service.h:

    typedef struct {
        uint8_t (*function1)(void);
        uint8_t (*function2)(void);
    } const service_struct_t;

    extern service_struct_t service_api ;

service.c:

    #include "service.h"

    static uint8_t foo(void){
         return 13+6;
    }
    static uint8_t bar(void){
         return 7*6;
    }

    service_struct_t service_api = {
        .function1 = foo,
        .function2 = bar,
    };

我需要存根(模拟、替换)这些函数,但我无权更改原始代码。我正在使用 gcc 来编译单元测试。我没能:


    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    uint8_t __real_foo(void);
    uint8_t __wrap_foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_foo();
        }
    }
    /* same for bar */


    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    uint8_t __real_service_api ;
    uint8_t __wrap_service_api = {
        .function1 = foo,
        .function2 = bar,
    }

    static uint8_t foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_service_api.function1();
        }
    }
    /* same for bar */


    #include "service.h"
    #define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
    service_struct_t backup_service_api = {
        .function1 = service_api.function1;
        .function2 = service_api.function2;
    }
    service_struct_t stub_service_api = {
        .function1 = foo;
        .function2 = bar;
    }

    uint8_t foo(void){
        if(ENABLE_STUB){
            return 1;
        }else{
            return __real_foo();
        }
    }/* same for bar */

    void service_poke_stub(bool_t enable_stubs){
        if(enable_stubs){
            service_api.function1 = stub_service_api.function1
            service_api.function2 = stub_service_api.function2
        }else{
            service_api.function1 = backup_service_api.function1
            service_api.function2 = backup_service_api.function2
        }
    }

非常感谢你的帮助

正如您已经发现的那样,您不能模拟结构中的函数。

所以这取决于你想测试什么:

  • 如果您想测试结构是否包含正确的功能,模块 service.c 是您的待测模块,应按原样使用。您需要通过观察函数执行的操作来检查正确性。

  • 如果你想测试结构是否被正确使用,你将模拟整个模块。现在你想放什么就放什么。

如果您的源代码不允许这样做,则该设计不利于测试。当架构没有考虑到可测试性时,通常会出现这种情况。