C语言单元测试:Ceedling框架下指针参数匹配问题
Ceedling单元测试:匹配
llist_remove_all参数的问题 问题描述
我在使用Ceedling框架做C语言单元测试时,遇到了参数匹配的问题:
测试代码中期望llist_remove_all接收的参数是&new_list,但被测试函数task_find_by调用该函数时,传入的是内部指针new的地址。虽然new和new_list指向同一个struct Person实例,但两个指针变量本身的内存地址不同,导致测试的参数匹配失败。现在需要在不修改task_find_by实现的前提下完成测试验证。
测试代码
struct Person *list; /* TASK_FIND_BY */ void test_main_task_find_by_normal(void) { char *string = (char *)malloc(sizeof(char)); struct Person new_list_instance; struct Person *new_list = &new_list_instance; ask_input_ExpectAndReturn(string); llist_find_by_ExpectAndReturn(list, string, new_list); llist_print_Expect(new_list); llist_remove_all_Expect(&new_list); printf("\nOutside single: %p\n", new_list); printf("Outside double: %p\n", &new_list); task_find_by(list); }
被测试函数
void task_find_by(struct Person *list) { char *input = NULL; struct Person *new = NULL; printf("Input exact name/surname/email/phone: "); input = ask_input(); if (input == NULL) { printf("Error!"); return; } new = llist_find_by(list, input); if (new != NULL) llist_print(new); else printf("Address not found!\n"); printf("\nInside single: %p\n", new); printf("\nInside double: %p\n", &new); free(input); llist_remove_all(&new); }
运行时地址输出
- "Outside single: 0x7ffc2e3c03d0"
- "Outside double: 0x7ffc2e3c03c0"
- "Inside single: 0x7ffc2e3c03d0"
- "Inside double: 0x7ffc2e3c0398"
解决方案
Ceedling依赖的CMock框架支持参数回调验证,可以绕过指针变量地址的严格匹配,转而验证指针指向的内容是否符合预期。具体步骤如下:
1. 修改测试代码,使用回调验证参数
把原来的llist_remove_all_Expect(&new_list)替换为「忽略参数匹配+回调验证」的逻辑,核心是检查llist_remove_all接收的指针(&new)指向的内容(即new的值)是否等于测试中的new_list。
修改后的测试代码:
struct Person *list; /* TASK_FIND_BY */ void test_main_task_find_by_normal(void) { char *string = (char *)malloc(sizeof(char)); static struct Person new_list_instance; static struct Person *new_list = &new_list_instance; // 定义参数验证回调:检查传入的二级指针指向的内容是否为预期的指针 void verify_llist_remove_all_arg(struct Person** arg) { TEST_ASSERT_EQUAL_PTR(new_list, *arg); } ask_input_ExpectAndReturn(string); llist_find_by_ExpectAndReturn(list, string, new_list); llist_print_Expect(new_list); // 替换原有的Expect,改为忽略参数并添加验证回调 llist_remove_all_ExpectAnyArg(); llist_remove_all_StubWithCallback((void*)verify_llist_remove_all_arg); printf("\nOutside single: %p\n", new_list); printf("Outside double: %p\n", &new_list); task_find_by(list); free(string); // 释放内存,避免测试内存泄漏 }
2. 原理说明
llist_remove_all_ExpectAnyArg():告诉CMock不严格匹配参数的具体地址,允许任意参数传入。llist_remove_all_StubWithCallback():注册一个回调函数,当llist_remove_all被调用时,CMock会将实际传入的参数(即task_find_by中的&new)传给这个回调。- 在回调
verify_llist_remove_all_arg中,通过TEST_ASSERT_EQUAL_PTR验证*arg(也就是new的值)是否等于new_list,这样就实现了我们需要的逻辑:只要new指向的是预期的struct Person实例,即使&new和&new_list地址不同,测试也能通过。
内容的提问来源于stack exchange,提问作者Mykolas D.
相关产品推荐
相关产品推荐

