C语言中的函数模拟?

7

我正在编写一个单元测试来检查一些API调用。我使用check进行测试。我的模块是使用CMake构建的(我不知道这是否重要)。

我的测试调用一个需要测试的函数,而这个函数又调用另一个二进制文件。

以下是它的简化版本。

/* unitTest.c */

#include "libraryAPI.h"
void letsMakeACall(void)
{
   ck_assert_eq(foo("water"), 0);
}

-- Module I am working on---
/*libraryAPI.c*/
#include "legacyLib.h"

void foo(const char *drink )    
{

    if (checkDrink(drink)!=0)
    {
       return 1;
    }else
    {
       return 0;
    }
}


----LEGACY BINARY---
/*legacyLib.c*/

static const char* expected = "water";

void checkDrink(const char *drink)
{
    if(drink == expected)
     {
        /*There are also a dozen functions being called which depend on legacy module initialisation*/
        return 0;
     }else{
        return 1;
     }
}

我希望能够模拟来自legacyLib的响应,否则它会调用数十个函数并中断。我的初始想法是在运行测试时添加一些ifdef条件,但这违反了指南。因为这基本上是一个调用拦截,我不知道什么是最好(或有效的)解决方案。我该使用什么来解决它?


如果你想测试一个函数,模拟它是没有意义的。 - Eugene Sh.
是的,但我想要模拟被我正在测试的函数调用的其中一个函数的响应。 - Oreols
2
那个函数定义在哪里?你能用“模拟”库替换实现该函数的库吗? - Eugene Sh.
1
拥有一个模拟库或DLL比一堆ifdef更加清晰。 - cdarke
我可以替换库,但最终测试必须在发布候选版本上运行。 - Oreols
我在这里问了一个类似的问题,有一个赏金,所以如果有人提供了一个好的答案,你也可以在几天后去那里看看。 - Lou
1个回答

8

我也不确定如何一般性地解决这个问题,我已经发布了一个类似的问题,但在某些情况下,您可以执行以下操作(假设您正在测试单个函数):

  1. Include the .c file instead of the header .h, but after you "rename" your mocked function using a define directive:

    #define checkDrink checkDrink_mocked
    // preprocessor will now replace all occurrences of "checkDrink"
    // with "checkDrink_mocked"
    
    int checkDrink_mocked(const char *drink); 
    #include "legacyLib.c"
    #undef checkDrink
    
  2. Implement the renamed function:

    int checkDrink_mocked(const char *drink)
    {
        return 15;  
    }
    

1
谢谢。我认为这是最好的解决方案。在我的情况下,它只是一个非常简单的getter-setter引用,所以我只是在我的模块中重新实现了它(减少了对愚蠢事物的依赖 :))。 - Oreols
1
很好,如果它起作用了那就太棒了。但是如果例如libraryAPI.c函数调用来自不同模块的某些外部函数,然后再回调libraryAPI.c中的原始函数(在这种情况下是checkDrink),那么这个方法很容易失败,因为链接器会找到原始函数。我发现了一个名为mimick(Snaipe/Mimick)的库(作者提到它仍处于alpha阶段),它通过更改运行时动态模块的“全局偏移表”中的条目来工作,但我还没有尝试过它(它显然支持GCC 4.6+、Clang 3.5+、MSVC 14+)。 - Lou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接