Appearance
Mock 功能
本章介绍 Anvil 的 Mock 系统,用于隔离测试和模拟外部依赖。
概述
Anvil Mock 允许你拦截和替换函数调用,用于:
- 模拟外部依赖(数据库、网络、硬件)
- 控制测试条件(模拟错误、边界值)
- 验证函数调用(参数、次数)
- 隔离被测代码
工作原理
Anvil 使用链接器的 --wrap 机制实现函数拦截:
原始调用链:
caller() → target_function()
Mock 后:
caller() → __wrap_target_function() → [可选] __real_target_function()- 原始函数重命名为
__real_target_function - Anvil 生成
__wrap_target_function作为新的入口点 - Mock 函数可以选择调用原始实现
两种 Mock 模式
用户实现模式
提供完整的函数体:
c
__attribute__((mock))
int read_sensor(int id) {
return 42; // 用户提供的实现
}声明式模式
仅声明函数,通过 API 配置行为:
c
__attribute__((mock))
int read_sensor(int id); // 仅声明
// 在测试中配置
mock(read_sensor).set_return(42);快速示例
c
#include "sensor.h"
#include <anvil/mock.h>
// Mock 传感器读取函数
__attribute__((mock))
int read_sensor(int sensor_id) {
return 25; // 固定返回 25 度
}
/*
* 设计说明:测试温度检查逻辑
* 预期结果:25度低于80阈值,返回0
*/
__attribute__((test_method))
int test_check_temperature(void) {
int result = check_temperature(0, 80);
return result == 0; // 低于阈值
}
/*
* 设计说明:验证传感器ID被正确传递
* 预期结果:应使用传感器ID 5
*/
__attribute__((test_method))
int test_sensor_id(void) {
mock(read_sensor).reset();
check_temperature(5, 80);
return mock(read_sensor).arg0_val == 5;
}
// includes: -I../include章节导航
重要限制
Mock 函数与调用者必须在不同文件
被 Mock 的函数定义必须在与调用者不同的 .c 文件中。这是链接器 --wrap 机制的要求。
✗ 错误:
src/module.c 中定义 foo(),同一文件调用 foo()
✓ 正确:
src/module_impl.c 中定义 foo()
src/module_caller.c 中调用 foo()