Skip to content

Mock API 参考

完整的 Anvil Mock API 文档。

头文件

c
#include <anvil/mock.h>

API 汇总

API用途返回类型
mock(func).call_count获取调用次数int
mock(func).arg(n)获取第 n 个参数(void*)void*
mock(func).argN_val获取第 N 个参数值参数类型
mock(func).history(i, n)获取历史调用参数void*
mock(func).reset()重置 Mock 状态void
mock(func).call_real(...)调用原始实现函数返回类型
mock(func).set_return(val)设置返回值void
mock(func).set_custom(fn)设置自定义实现void

调用追踪

call_count

获取 Mock 函数被调用的次数:

c
mock(read_sensor).reset();

read_sensor(0);
read_sensor(1);
read_sensor(2);

int count = mock(read_sensor).call_count;  // count = 3

arg(n)

获取最后一次调用的第 n 个参数,返回 void*

c
send_data("hello", 5);

const char *data = *(const char **)mock(send_data).arg(0);  // "hello"
int len = *(int *)mock(send_data).arg(1);  // 5

类型转换

arg(n) 返回 void*,需要手动转换类型。对于简单类型,推荐使用 argN_val

argN_val

类型安全地获取第 N 个参数值(N = 0, 1, 2, ...):

c
send_data("hello", 5, 1);

// 直接获取值,无需类型转换
int len = mock(send_data).arg1_val;     // 5
int flag = mock(send_data).arg2_val;    // 1

支持的参数索引:arg0_val, arg1_val, arg2_val, ..., arg9_val

history(i, n)

获取第 i 次调用的第 n 个参数:

c
read_sensor(10);
read_sensor(20);
read_sensor(30);

// 获取历史调用参数
int first_id = *(int *)mock(read_sensor).history(0, 0);   // 10
int second_id = *(int *)mock(read_sensor).history(1, 0);  // 20
int third_id = *(int *)mock(read_sensor).history(2, 0);   // 30

状态控制

reset()

重置 Mock 状态,清除调用计数和参数历史:

c
mock(read_sensor).reset();

// call_count 变为 0
// 参数历史被清空

最佳实践

test_initialize 中重置所有 Mock:

c
__attribute__((test_initialize))
int setup(void) {
    mock(func1).reset();
    mock(func2).reset();
    return 0;
}

call_real(...)

调用原始函数实现:

c
__attribute__((mock))
int calculate(int x, int y) {
    // 记录调用
    log_call(x, y);

    // 调用原始实现
    return mock(calculate).call_real(x, y);
}

行为配置(声明式模式)

set_return(val)

设置 Mock 函数的返回值:

c
__attribute__((mock))
int read_sensor(int id);

mock(read_sensor).set_return(42);
int value = read_sensor(0);  // value = 42

set_custom(fn)

设置自定义实现函数:

c
__attribute__((mock))
int calculate(int a, int b);

int my_impl(int a, int b) {
    return a * b;
}

mock(calculate).set_custom(my_impl);
int result = calculate(3, 4);  // result = 12

完整示例

c
#include "network.h"
#include <anvil/mock.h>

__attribute__((mock))
int net_send(int fd, const char *data, int len);

__attribute__((mock))
int net_recv(int fd, char *buf, int len);

__attribute__((test_initialize))
int setup(void) {
    mock(net_send).reset();
    mock(net_recv).reset();
    return 0;
}

/*
 * 设计说明:验证发送次数
 * 预期结果:应调用 send 3 次
 */
__attribute__((test_method))
int test_send_count(void) {
    mock(net_send).set_return(5);

    batch_send(3, "hello");

    return mock(net_send).call_count == 3;
}

/*
 * 设计说明:验证发送参数
 * 预期结果:参数正确
 */
__attribute__((test_method))
int test_send_params(void) {
    mock(net_send).set_return(5);

    do_send(10, "test", 4);

    int fd = mock(net_send).arg0_val;
    const char *data = *(const char **)mock(net_send).arg(1);
    int len = mock(net_send).arg2_val;

    return fd == 10 &&
           strcmp(data, "test") == 0 &&
           len == 4;
}

/*
 * 设计说明:验证历史调用
 * 预期结果:每次调用参数正确
 */
__attribute__((test_method))
int test_send_history(void) {
    mock(net_send).set_return(1);

    net_send(1, "a", 1);
    net_send(2, "b", 1);
    net_send(3, "c", 1);

    int fd1 = *(int *)mock(net_send).history(0, 0);
    int fd2 = *(int *)mock(net_send).history(1, 0);
    int fd3 = *(int *)mock(net_send).history(2, 0);

    return fd1 == 1 && fd2 == 2 && fd3 == 3;
}

// includes: -I../include

生成的文件位置

Mock 代码生成在临时目录:

/tmp/anvil-mocks/<测试文件名>/
├── __anvil_mock_net_send.c
├── __anvil_mock_net_recv.c
└── ...

使用 anvil -c 保留这些文件用于调试。

本页面内容遵循 Luna 软件源代码授权条款 (LSLA) 发布