有时,我们需要进行模拟测试。进行依赖项注入的最广泛使用的方法是使用模板或接口。
但是,有时候,对于一些遗留代码,存在一些没有虚函数和模板的具体类。由于某些原因,我们不想或不能修改生产代码。但是我们仍然想对具体的类进行模拟测试。
已经有很多关于该主题的讨论。大多数人说,做到这一点非常困难,即使不是不可能。
幸运的是,我似乎已经找到了黎明。
(1)帕维尔·米纳耶夫(Pavel Minaev)在Interfaces vs Templates for dependency injection in C++中的an口
使用C ++,还有另一个选择-您可以给模拟类精确 与真实类的名称相同,并且在链接单元测试时, 将它们与模拟对象/库文件(而不是真实文件)链接。
(2)SDG在fake/mock nonvirtual C++ methods中的答案
我们有时使用的一种方法是将原始.cpp文件拆分为 至少两部分。
然后,测试设备可以提供自己的实现; 有效地使用链接器为我们完成肮脏的工作。
在某些圈子中,这被称为“链接缝”。
理论上是的。我们可以以一个简单的案例为例进行演示。
一个简单的程序存在两个类,A
和B
。 B是A的用户。
当我们要进行类B的单元测试时,我们可以在A
中定义另一个MockA.cpp
。并通过以下命令生成单元测试执行文件。
g++ testB.cpp B.cpp MockA.cpp
发布时间到了,我们可以通过Follow命令生成可执行文件
g++ Main.cpp B.cpp A.cpp
我的问题是,我们如何才能在大型程序中实现它?
这是一个真实的程序,可能存在很多类,它们被打包到库中。
例如:
一个庞大的程序需要使用两个库。 libA
来自类A1,A2,A3,...A100
。 libB
来自类B1,B2,B3,....B100
。
假设我们要对B3进行单元测试,并且希望A1
,A2
,B1
,B2
被模拟。我们该怎么做?
我们需要一个libA without A1,A2
,libB without B1,B2
,MockA1
,MockA2
,MockB1
,MockB2
吗?
此外,如果B4
,B5
,B6
都需要做类似B3
的事情,这似乎非常复杂。
手动操作很复杂,很容易犯错误并且很难维护。
我不知道如何让链接程序为我们做肮脏的工作?
上面链接中的某人说该技术已被用于实践项目中。但是我学习了很多,却一无所知。
任何已经使用此技术的开源项目链接将非常有帮助。使用CMake或Makefile进行编译对我来说甚至更好。
感谢您的时间。
修改 Mike van Dyke分享了另一种无需虚拟功能即可进行模拟的方法。 该方法可以进行模拟工作,而无需使用链接器。这是进行模拟的另一种解决方案。 Using googlemock with fake impls of non-virtual functions
答案 0 :(得分:1)
我了解您的情况如下:为了测试B3
,您需要真实的B3
以及A1
,A2
,B1
和{{1 }}。您的假设是,您将使用与生产代码类似的库设置:将存在一个包含B2
,B3
,B4
的库,但肯定没有{{1 }}和B5
,因为它们将被嘲笑。
对于单元测试可执行文件,我的建议是选择不同的库设置:创建单独的库B1
,B2
等,并为模拟的libMockA1
类创建单独的库。然后,您可以在构建测试可执行文件时更独立地组合它们。为了测试libMockA2
,您可以将Bx
对象文件与B3
,B3
,libMockA1
和libMockA2
链接。为了测试libMockB1
,您可以将libMockB2
对象文件与B4
,B4
和libMockA1
等链接起来。
或者,您可以完全放弃使用库进行单元测试,而只单独链接目标文件。
您仍然需要为libMockB1
和libMockB3
类创建模拟,但是您可以为每个测试可执行文件单独组合它们-无需为每个测试创建不同配置的库可执行文件。