Skip to content

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()

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