从这篇文章中使用 C 中的模拟对象进行单元测试:
这是通过使用
--wrap链接器选项来完成的,该选项将包装函数的名称作为参数。如果测试是使用 gcc 编译的,则调用可能如下所示:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
在 Visual Studio 中编译 C 项目时如何做到这一点?
我试图在C中模拟一个函数,当函数及其调用函数在不同的文件中定义时,mocking工作正常.但是当两个函数(函数本身及其调用者)在同一文件中定义时,不会调用模拟函数.
情况1 :
//test.c
#include <stdio.h>
/*mocked function*/
int __wrap_func() {
printf("Mock function !!!\n");
}
/*caller function*/
int myTest() {
return func();
}
int main() {
myTest();
return 0;
}
//file.c
#include<stdio.h>
/*function need to be mocked*/
int func() {
printf("Original function !!!\n");
}
Run Code Online (Sandbox Code Playgroud)
案例2:
//test.c
#include <stdio.h>
extern int myTest();
/*mocked function*/
int __wrap_func() {
printf("Mock function !!!\n");
}
int main() {
myTest();
}
//file.c
#include<stdio.h>
/*function need to be mocked*/
int func() {
printf("Original function !!!\n");
}
/*caller …Run Code Online (Sandbox Code Playgroud) 我在做什么:
我正在使用cmocka对大型嵌入式项目运行单元测试。嵌入式项目使用编译arm-gcc-compiler。单元测试是gcc使用嵌入代码和cmocka库的片段与普通代码一起编译的。
通常,cmocka建议使用该-Wl,--wrap=functionName标志来模拟(替换)一些不需要的子功能。这个效果很好。
问题:
好吧,在我的嵌入式代码中,有一个头文件(foo.h),其中包含一些函数(声明为内联)。这些函数之一包含的一些汇编代码arm-gcc-compiler,当然,这些不能被编译gcc。
愣神的wrap-flag似乎并没有被放置在头文件中的函数工作。
题:
如何在头文件中模拟该功能呢?
我如何解决问题:
我考虑过要插入一些#idef宏以排除提到的汇编器部分。但这无法完成,因为此文件属于许可库,并且不允许更改其内容。
我可以将待测函数提取到其他文件中,这样foo.h就不再需要包含它了。但这会混淆嵌入式源代码的结构。
确切的问题
确切的代码位于233行的freeRtos的portmacro.h中:
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
__asm volatile
(
" mov %0, %1 \n" \
" msr basepri, %0 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
);
}
Run Code Online (Sandbox Code Playgroud)
其中portFORCE_INLINE定义为:
#define portFORCE_INLINE inline …Run Code Online (Sandbox Code Playgroud) 我刚刚开始使用 Cmocka,我已经在这个问题上停留了一段时间了。我有一个正在尝试构建的 cmocka 项目。当我尝试使用“make”时,我看到了错误。
[错误] --- 没有符号 __wrap_i2c_read 的条目。
另外,我在我调用的行的mock_i2c.c 文件中看到一个错误mock()
无法获取模拟函数 __wrap_i2c_read 的值。
现在我只是想模拟一个真/假值以使其正常工作。所以我的模拟看起来像
bool __wrap_i2c_read(void)
{
return (mock());
}
Run Code Online (Sandbox Code Playgroud)
我在测试中检查过我正在打电话will_return(__wrap_i2c_read, true);
在我的 Makefile 中,我已将LDFLAGS += -Wl,--wrap=i2c_read
其cmocka.h包含在mock_i2c.c 文件中。
对于这个模拟函数来说,这似乎不是一个问题,因为如果我不使用它,那么该文件中的其他模拟函数也会出现相同的错误。我不确定还需要什么其他信息,请告诉我。有人知道这意味着什么/以前见过这个吗?
谢谢。
编辑:所以我想我已经弄清楚为什么会出现此错误。for我正在测试的函数中有一个循环。从此函数调用模拟函数。一旦我删除循环,错误就会消失。will_return这可能与如何/何时对模拟值进行排队有关吗?循环for会妨碍吗?
Edit2:好的,看来我只是没有排队足够的模拟值。
因此,玩具程序重复了我使用 cmocka 为现有代码开发单元测试时遇到的问题。问题是嵌套函数调用不会模拟,这使得单元测试依赖于正确执行的嵌套函数调用。请注意,使用“mockable_static”定义是因为原始代码具有作为“内部函数调用”存在的静态函数,但出于单元测试的目的,这些对外部调用开放。(请参阅此想法来自的 stackoverflow 帖子)
废话不多说,代码如下:
函数.h:
#ifndef FUNC_H_
#define FUNC_H_
#ifdef UNIT_TESTING
#define mockable_static
mockable_static char* bar();
#endif
char* foo();
#endif // FUNC_H_
Run Code Online (Sandbox Code Playgroud)
功能.c:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef UNIT_TESTING
#define mockable_static static
#else
#define mockable_static
#endif
mockable_static char* bar (){
printf("This is bar!\n");
char *str = "This is the result of bar!";
return str;
}
char* foo(){
printf("This is foo, and it should return the results of bar()\n");
char * res;
res = bar(); …Run Code Online (Sandbox Code Playgroud) 我正在使用cmocka库来测试一些嵌入式 c 代码。根据文档,我使用__wrap_前缀来模拟函数,这样我就可以隔离我的单元测试。但是,一旦我这样做了,所有对该函数的调用将永远转到被包装的函数。如何在某些情况下重新启用真正的功能,以便我可以测试它或允许其他功能使用它?在我看来,唯一的方法是使用全局字段作为开关来调用真正的函数,如下所示:
int __wrap_my_function(void) {
if (g_disable_wrap_my_function) {
return __real_my_function();
}
// ... do mock stuff
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
我安装了CMocka 测试框架并尝试了示例代码:
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
(void) state; /* unused */
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(null_test_success),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译时,出现以下错误:
$ gcc -o Tests tests.c
/tmp/ccbwAXrr.o: In function `main':
tests.c:(.text+0x5e): undefined reference to `_cmocka_run_group_tests'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
我能够使用cmocka并在屏幕上获取默认结果。我想以JUnit格式获取单元测试的结果。
CMocka通过使用env变量CMOCKA_MESSAGE_OUTPUT或使用API 支持JUnit格式cmocka_set_message_output(CM_OUTPUT_XML);
但是仍然没有生成xml文件。任何人都可以帮助获得JUnit格式的结果吗?
假设我声明了一个名为 foo 的 C 结构,它有一个名为 bar 的 int 字段和一个名为 baz 的 char *。
如何使用Cmocka expect_和check_expected宏来检查传递的结构是否正确以及两个字段是否具有预期值?如果文档中有示例,我错过了。
[更新] 也许我可以使用expect_check()?但我找不到一个例子:-(
我正在开发一个使用 cmocka 框架的项目。cmocka 主页指出
测试装置是设置和拆卸功能,可以在多个测试用例之间共享,以提供准备测试环境并随后销毁它的通用功能。
如果我用看起来像这样的代码运行我的测试
int main(void) {
const struct CMUnitTest license_tests[] = {
cmocka_unit_test(test_setup),
cmocka_unit_test(test_null_app),
cmocka_unit_test(test_null_name),
};
return cmocka_run_group_tests(license_tests, NULL, NULL);
}
Run Code Online (Sandbox Code Playgroud)
我如何/在哪里可以指示 cmocka 运行安装/拆卸装置以及 cmocka 具有哪些功能(如果有)让我访问在所述装置中创建的内容?
我最近遇到了 C 的“ cmocka ”模拟库。我能够模拟单个函数并成功测试调用者函数。现在我需要它来将它用于我正在开发的项目,该项目需要模拟大量函数。如何将我想要模拟的所有函数传递给 Linker 的 'wrap' 参数?是否可以将函数名称存储在文件中,以便链接器可以获取它?