19

我是一个相当新的软件开发人员,目前正在向多年前开始的现有 C++ 项目添加单元测试。由于非技术原因,我不允许修改任何现有代码。我所有模块的基类都有一堆设置/获取数据和与其他模块通信的方法。

因为我只想对每个单独的模块进行单元测试,所以我希望能够为我的所有模块间通信方法使用固定值。即对于检查另一个模块是否处于活动状态的方法 Ping(),我希望它根据我正在做的测试类型返回 true 或 false。我一直在研究 Google Test 和 Google Mock,它确实支持模拟非虚拟方法。然而,所描述的方法(http://code.google.com/p/googlemock/wiki/CookBook#Mocking_Nonvirtual_Methods)要求我将原始方法“模板化”以获取真实或模拟对象。由于前面提到的要求,我不能在基类中模板化我的方法,所以我需要一些其他方法来模拟这些虚拟方法

基本上,我想模拟的方法在某个基类中,我想单元测试和创建模拟的模块是该基类的派生类。在我的基本 Module 类和我想要测试的模块之间有中间模块。

我将不胜感激任何建议!

谢谢,

JW

编辑:更具体的例子

我的基类是 rootModule,我要测试的模块是 leafModule。有一个继承自rootModule的中间模块,leafModule继承自这个中间模块。

在我的leafModule 中,我想测试doStuff() 方法,该方法调用rootModule 类中定义的非虚拟GetStatus(moduleName)。我需要以某种方式使 GetStatus() 返回一个选定的罐头值。模拟对我来说是新的,所以使用模拟对象甚至是正确的方法吗?

4

3 回答 3

14

有一些不同的方法可以替换非虚拟函数。一种是重新声明它们并为您想要测试的每组不同的非虚拟函数编译一个新的测试可执行文件。这很难扩展。

第二种选择是将它们虚拟化以进行测试。大多数编译器允许你在命令行上定义一些东西,所以用 -DTEST_VIRTUAL=virtual 或 -DTEST_VIRTUAL 编译你的代码,使它们成为虚拟的或正常的,这取决于它是否在测试中。

可能可用的第三个选项是使用模拟框架,让您模拟非虚拟函数。我是 HippoMocks 的作者(关于中立性等的免责声明),我们最近添加了在 X86 平台上模拟纯 C 函数的能力。这可以通过一些工作扩展到非虚拟成员函数,这就是您正在寻找的。请记住,如果您的编译器可以同时看到函数的使用和定义,那么它可能会内联它并且模拟可能会失败。这尤其适用于在标头中定义的函数。

如果常规的 C 函数模拟对您来说已经足够了,您可以照原样使用它。

于 2010-05-18T13:41:46.547 回答
3

我会编写一个 Perl/Ruby/Python 脚本来读取原始源代码树并在不同的目录中写出一个模拟的源代码树。您不必完全解析 C++ 来替换函数定义。

于 2010-02-26T05:08:56.937 回答
2

一种方法是指定不同的测试来源。假设您的生产目标使用rootModule.hand rootModule.cpp。为您的测试目标使用不同的来源。您可以通过更改包含路径来指定不同的标头,以便#include "rootModule.h"实际加载unittest/rootModule.h. 然后将 rootModule 模拟到您的内心深处。

于 2010-02-26T06:10:58.367 回答