Mock/Wrap 被测非静态函数调用的静态函数

Mock/Wrap static functions called by a non-static function under test

我想通过使用 cmocka 框架实现单元测试来测试一些功能。

例如,我有一个正在测试的非静态函数,它调用两个静态函数。由于这些静态函数与硬件交互,我想 mock/wrap 它们并在测试时使用包装函数而不是真正的函数。

如 cmocka 文档中所述,我在 building/linking 我的测试中使用了 --wrap=myfunction 链接器标志。

测试可以编译,但是当我 运行 它们时,将调用真正的静态函数而不是包装。

当我将静态函数声明为非静态时,它也不起作用,并且还会调用实际函数。我找到的唯一解决方案是将函数外包到一个额外的 .c 文件中...但这是一个非常糟糕的解决方法,因为它对代码的操作非常多。

如果您有一个.c 文件,其中包含一个public 函数和两个静态函数,并且public 函数调用静态函数,那么您无法阻止静态函数被调用。毕竟是一个编译单元

您可以:

  • 整体测试

  • 使用#ifdef条件编译将静态函数替换为简化的非硬件调用静态函数来测试public函数

  • 使用#ifdef条件编译将public函数替换为专门的public函数来测试静态函数。

正如@Paul 所写,这就是 --wrap 的工作原理,如果您希望 gcc 包装这些函数,则这些函数需要位于不同的编译单元中。通常,静态方法是您不想公开进行测试的私有实现细节。

所以要为其他答案添加更多选项:

  1. 显然,在不使用条件污染原始代码的情况下模拟这些函数的最简单方法是将它们提取到单独的层(在本例中为 HAL)。

  2. 您可以使 static 修饰符成为条件,这将允许使用 cmocka 进行换行。与一堆 #ifdefs:

    相比,这对原始代码的污染更少
    #ifndef UNIT_TESTING
    #  define mockable_static static
    #else
    #  define mockable_static
    #endif
    
    // then, replace 'static' with 'mockable_static'
    mockable_static void some_static_method(void) {
       ... 
    }
    
  3. 使用 objcopy 全局化和弱化选定的静态函数,如 this answer.

  4. 中所述