c - C 中的函数模拟(用于测试)?

标签 c unit-testing linker mocking

我想用 C 为 C 库编写测试。我想为测试模拟一些函数。

假设我的库是从以下来源编译的:

/* foo.h */
int myfunction(int x, int y);

/* foo.c */
#include "foo.h"

static int square(int x) { return x * x; }

int myfunction(int x, int y) {
    return square(x) + square(y);
}

我想写一个这样的测试:

/* foo_test.c */
#include "foo.h"

static int square(int x) { return x + 1; }

int main(void) {
    assert(myfunction(0, 0) == 2);
    return 0;
}

有没有什么方法可以让 myfunction 使用 foo_test.csquare 的定义,而不是foo.c,仅在链接可执行文件foo_test时?也就是说,我想将 foo.c 编译成一个库(我们称它为 libfoo.so),然后用 foo_test.c 编译libfoo.so 和一些魔法,这样我就可以得到一个可执行文件 foo_test,它使用 square 的不同实现。

听到 square 未声明为 static 时的解决方案会很有帮助,但解决上述情况会更好。

编辑:这似乎没有希望,但有一个想法:假设我用 -O0 -g 编译,所以 square 不太可能被内联,我应该显示符号解决调用的地方。有没有办法潜入目标文件并换出已解析的引用?

最佳答案

我写了Mimick ,一个用于解决此问题的 C 函数的模拟/ stub 库。

假设 square 既不是静态的也不是内联的(因为否则它会绑定(bind)到编译单元和使用它的函数)并且你的函数是在一个名为“libfoo.so”的共享库(或任何你的平台的命名约定是),这就是你要做的:

#include <stdlib.h>
#include <assert.h>
#include <mimick.h>

/* Define the blueprint of a mock identified by `square_mock`
   that returns an `int` and takes a `int` parameter. */
mmk_mock_define (square_mock, int, int);

static int add_one(int x) { return x + 1; }

int main(void) {
    /* Mock the square function in the foo library using 
       the `square_mock` blueprint. */
    mmk_mock("square@lib:foo", square_mock);

    /* Tell the mock to return x + 1 whatever the given parameter is. */
    mmk_when(square(mmk_any(int)), .then_call = (mmk_fn) add_one);

    /* Alternatively, tell the mock to return 1 if called with 0. */
    mmk_when(square(0), .then_return = &(int) { 1 });

    assert(myfunction(0, 0) == 2);

    mmk_reset(square);
}

不过,这是一个成熟的模拟解决方案,如果您只想 stub square(而不关心测试交互),您可以做类似的事情:

#include <stdlib.h>
#include <assert.h>
#include <mimick.h>

static int my_square(int x) { return x + 1; }

int main(void) {
    mmk_stub("square@lib:foo", my_square);

    assert(myfunction(0, 0) == 2);

    mmk_reset(square);
}

Mimick 的工作原理是对正在运行的可执行文件使用一些内省(introspection),并在运行时对全局偏移表进行中毒,以将函数重定向到我们选择的 stub 。

关于c - C 中的函数模拟(用于测试)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8959132/

相关文章:

在 Mac OS X 上使用 libpng 编译 C 程序

c - 如何用256位AVX vector 对两个复数 double 平方?

c++ - 单程搜索和替换

python - 值错误 : invalid literal for int() with base 10: '30.0' when running unittest

c - 将图书馆中的图书馆与外部人员联系起来?

c++ - 链接描述文件条件包含

c - 交替位置&否定。使用 For 循环在几何级数中

c - 使用库函数存储值时结构中的变量损坏

database - 在事务中包装 visual studio 数据库单元测试以消除持久的数据库更改

java - 使用 ReflectionTestUtils 模拟静态类