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

在C+中模拟非虚方法+;不编辑生产代码? 我是一个相当新的软件开发人员,目前正在向一个多年前开始的C++项目添加单元测试。由于非技术原因,我不允许修改任何现有代码。我所有模块的基类都有一系列方法用于设置/获取数据以及与其他模块通信,c++,unit-testing,mocking,googlemock,C++,Unit Testing,Mocking,Googlemock,因为我只想对每个模块进行单元测试,所以我希望能够对所有模块间通信方法使用固定值。例如,对于检查另一个模块是否处于活动状态的方法Ping(),我希望它根据我正在进行的测试类型返回true或false。我一直在研究GoogleTest和GoogleMock,它确实支持模拟非虚拟方法。然而,所描述的方法()要求我将原始方法“模板化”,以接受真实或模拟对象。由于前面提到的要求,我无法在基类中对我的方法进行模板化,因此我需要一些其他方法来模拟这些虚拟方法 基本上,我想要模拟的方法是在某个基类中,我想要单元

因为我只想对每个模块进行单元测试,所以我希望能够对所有模块间通信方法使用固定值。例如,对于检查另一个模块是否处于活动状态的方法Ping(),我希望它根据我正在进行的测试类型返回true或false。我一直在研究GoogleTest和GoogleMock,它确实支持模拟非虚拟方法。然而,所描述的方法()要求我将原始方法“模板化”,以接受真实或模拟对象。由于前面提到的要求,我无法在基类中对我的方法进行模板化,因此我需要一些其他方法来模拟这些虚拟方法

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

如果有任何建议,我将不胜感激

谢谢

JW

编辑:更具体的示例

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


在我的leafModule中,我想测试doStuff()方法,该方法调用在rootModule类中定义的非虚拟GetStatus(moduleName)。我需要以某种方式使GetStatus()返回所选的固定值。mock对我来说是新事物,使用mock对象是否是正确的方法?

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

< P>一种方法是指定不同的源进行测试。假设您的生产目标使用
rootModule.h
rootModule.cpp
。为您的测试目标使用不同的源。您可以通过更改include路径来指定不同的头,以便
#include“rootModule.h”
实际加载
unittest/rootModule.h
。然后尽情地模仿rootModule。

替换非虚拟函数有几种不同的方法。一种是重新声明它们,并为要测试的每一组不同的非虚拟函数编译一个新的测试可执行文件。这几乎是不可伸缩的

第二种选择是将它们虚拟化以供测试。大多数编译器都允许您在命令行上定义某些内容,因此可以使用-DTEST_VIRTUAL=VIRTUAL或-DTEST_VIRTUAL编译代码,使其成为虚拟或正常,具体取决于是否正在测试

第三个可用的选项是使用模拟框架来模拟非虚拟函数。我是HippoMocks(关于中立性等的免责声明)的作者,我们最近增加了在X86平台上模拟普通C函数的功能。这可以通过一些工作扩展到非虚拟成员函数,这将是您所需要的。请记住,如果编译器可以同时看到函数的使用和定义,那么它可能会内联函数,模拟可能会失败。它特别适用于在标头中定义的函数


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

您是否可以仅为测试在本地修改代码?您不必签入更改。是否需要使用单元测试?还有其他(自动化的)回归测试方法。单元测试是一种工具,而不是一种宗教——如果它不适合,就不要使用它。理想情况下,我的团队希望使用单元测试,因为我们的模块树相当大,我们真的希望将模块间功能的测试与模块本地方法的测试分离。不幸的是,我们以前的设计决策使单元测试成为一种挑战。你指的是什么其他回归测试方法?我想,使用其他测试方法,我们仍然需要某种方式来设置非虚拟方法或返回固定值,这意味着我们要么找到解决方法,要么保留另一个源代码树。Google Mocks cookbook链接+1。我确实有这个问题,但由于“模板化”方法已经成为我设计的一部分,所以听起来它对我来说可能是理想的。这可能会起作用,但是在IMO中,如果只有两个源树,并且在其中一个中将基类方法更改为虚拟的,则会更简单。会有一些不利因素影响到负责源代码管理系统的人。开发人员还必须调整自己,为2个工作版本编写代码。我要寻找的是一种变通方法,它可以让我将单元测试集成到一个可以在一次过程中构建(和执行)的源代码树中。我不确定的是,这是否可能。@wk1989:开发人员永远不会用脚本的思想在两个源代码树上工作。这就是重点。所有代码编辑都将在真正的代码树上完成。测试将从脚本生成的测试树上运行。我刚刚找到了这个答案。我打算使用Hippomock已经有一段时间了(第一次使用模拟框架),但我倾向于使用模板进行编译时依赖项注入,我不确定Hippomock是否能够做到这一点。您能进一步解释一下模拟非虚拟成员函数需要什么?为什么内联会导致模拟失败呢?非虚拟成员函数可以由