You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Mock代码开发中消除文件依赖问题求助

解决Mock开发中无法消除被Mock文件依赖的问题

我之前在基于nRF SDK做单元测试Mock的时候,也碰到过几乎一模一样的问题——SDK的头文件依赖链拉得特别长,Mock文件一包含原始头文件,就会把整个SDK的依赖都带进来,编译时一堆报错。结合我的实践经验,给你几个可行的解决方案:

1. 用前置声明替代直接包含原始头文件

如果你的Mock代码只需要用到原始头文件里的类型名称或者函数声明,而不需要访问结构体内部成员的话,完全可以用前置声明来替代#include

比如原本你的Mock头文件里写了:

#include "ble_service.h" // 这个会间接引ble.h、ble_gap.h以及一堆SDK头文件

你可以改成:

// 前置声明结构体
typedef struct ble_service_s ble_service_t;
// 前置声明需要Mock的函数
void ble_service_init(ble_service_t* p_service);
uint32_t ble_service_send_data(ble_service_t* p_service, uint8_t* data, uint16_t len);

这样就彻底切断了对原始头文件及其依赖的引用,编译时不会再去拉ble_gap.h那些文件了。

⚠️ 注意:如果你的Mock代码需要访问结构体的内部成员,这个方法就不适用了,得用下面的方案。

2. 自定义最小化Stub头文件替代原始头文件

针对需要访问结构体成员的场景,你可以自己写一个极简的Stub头文件,只保留Mock测试需要的内容,完全替换掉原始的SDK头文件。

比如创建一个mock_ble_service.h,里面只写你需要的结构体定义和函数:

typedef struct {
    uint8_t conn_handle; // 只保留Mock测试用到的成员
    uint8_t service_uuid;
} ble_service_t;

void ble_service_init(ble_service_t* p_service);
uint32_t ble_service_send_data(ble_service_t* p_service, uint8_t* data, uint16_t len);

然后在编译测试代码的时候,用-I参数把Stub头文件所在的目录放在SDK头文件目录的前面,让编译器优先找到你的Stub:

gcc -I./test/mock_headers -I../nRF5_SDK_11.0.0_89a8197/components/... test_ble_service.c -o test_ble_service

这样编译器就会用你写的mock_ble_service.h,而不是原始的ble_service.h,自然就不会引入那些冗余的依赖了。

3. 用条件编译隔离依赖

如果可以修改原始代码(或者你愿意复制一份原始头文件做修改),可以用条件编译来在Mock模式下跳过复杂依赖。

比如修改ble_service.h(或者复制一份到Mock目录修改):

#ifdef MOCK_MODE
// Mock模式下的极简定义
typedef struct {
    uint8_t dummy_conn_handle;
} ble_service_t;

void ble_service_init(ble_service_t* p_service);
#else
// 原始代码,包含完整依赖
#include "ble.h"

typedef struct {
    ble_gap_conn_params_t conn_params;
    // ... 其他原始成员
} ble_service_t;

uint32_t ble_service_init(ble_service_t* p_service, const ble_service_init_t* p_init);
#endif

然后编译测试代码的时候加上-DMOCK_MODE参数:

gcc -DMOCK_MODE -I../test/mock_headers test_ble_service.c -o test_ble_service

这样编译时就会走Mock模式的代码,不会包含ble.h及其后续的依赖。

4. 借助Mock框架自动处理依赖

如果你的项目是用C语言做单元测试,推荐试试CMock(配合Unity测试框架)这类专门的Mock工具。它可以自动解析原始头文件,生成对应的Mock代码,并且自动处理依赖问题——会自动生成前置声明或者Stub,不需要你手动去处理复杂的头文件依赖链。

比如用CMock的话,只需要在配置文件里指定要Mock的头文件ble_service.h,它就会生成ble_service_mock.cble_service_mock.h,这些生成的文件已经帮你隔离了原始SDK的依赖,直接用就行。


内容的提问来源于stack exchange,提问作者Faisal Kabariti

火山引擎 最新活动