【发布时间】:2016-08-02 21:16:19
【问题描述】:
我正在阅读几篇关于模拟 C 函数的文章(如 CMock 或 CMocka),但我不确定在此过程中如何将实际函数替换为模拟函数。例如,CMocka 依赖于使用 GNU 编译器的自动包装,它支持像 --wrap 这样的参数,将 __wrap 前缀附加到函数调用,或者 weak symbols 允许您覆盖任何您喜欢的符号.
但是对于几乎所有其他框架,您如何在 Visual Studio 中执行此操作?
例如CMock has an example类似这样(这里简化了很多):
// myfunc.c
#include <parsestuff.h>
// this is the function we would like to test
int MyFunc(char* Command)
{
// this is the call to the function we will mock
return ParseStuff(Command);
}
还有实际的实现,它包含链接器在实际应用程序中应该找到的实际功能:
// parsestuff.c
int ParseStuff(char* cmd)
{
// do some actual work
return 42;
}
现在,在测试期间,Ruby 脚本会创建模拟函数,例如:
// MockParseStuff.c (auto created by cmock)
int ParseStuff(char* Cmd);
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);
但是如果VS项目中已经包含
parsestuff.c,那么来自myfunc.c的调用怎么可能以MockParseStuff.c结束呢?这是否意味着我不能将
parsestuff.c包含在单元测试项目中?但是如果是这种情况,那么在任何测试中也不可能从myfunc.c模拟MyFunc,因为我已经必须包含该文件才能对其进行测试?
(更新)我也知道我可以包含 .c 文件而不是 .h 文件,然后做一些预处理器来替换原始调用,例如:
// replace ParseStuff with ParseStuff_wrap
#define ParseStuff ParseStuff_wrap
// include the source instead of the header
#include <myfunc.c>
#undef ParseStuff
int ParseStuff_wrap(char* cmd)
{
// this will get called from MyFunc,
// which is now statically included
}
但这似乎需要很多管道,我什至没有看到任何地方提到它。
【问题讨论】:
-
This question 询问了有关配置链接器以包装函数的具体问题,但我相信这在 MSVC 中是不可能的。另外,CMocka 提到了这一点,但 CMock 根本没有提到这个要求。
-
你必须在 C++ 环境中模拟 C 风格的函数,还是只有 C 环境?如果你会使用 C++,有一个非常简单的解决方案可以解决你的问题,我可以提供一个示例。
-
@mrAtari:它是 Visual Studio,所以我可以混合使用 C++ 和 C,但是可能存在某些 C 代码与 C++ 不兼容的问题(例如,检查 this similar question)。但是,如果它在大多数情况下都有效,请务必提供 C++ 如何解决此问题的示例 - 特别是如果它可以避免将任何与测试相关的预处理器指令添加到生产代码中。
标签: c visual-studio unit-testing mocking cmock