如何通过C ++中的链接器进行模拟测试

时间:2019-12-06 11:10:20

标签: c++ unit-testing linker mocking

有时,我们需要进行模拟测试。进行依赖项注入的最广泛使用的方法是使用模板或接口。

但是,有时候,对于一些遗留代码,存在一些没有虚函数和模板的具体类。由于某些原因,我们不想或不能修改生产代码。但是我们仍然想对具体的类进行模拟测试。

已经有很多关于该主题的讨论。大多数人说,做到这一点非常困难,即使不是不可能。

幸运的是,我似乎已经找到了黎明。

(1)帕维尔·米纳耶夫(Pavel Minaev)在Interfaces vs Templates for dependency injection in C++中的an口

  

使用C ++,还有另一个选择-您可以给模拟类精确   与真实类的名称相同,并且在链接单元测试时,   将它们与模拟对象/库文件(而不是真实文件)链接。

(2)SDG在fake/mock nonvirtual C++ methods中的答案

  

我们有时使用的一种方法是将原始.cpp文件拆分为   至少两部分。

     

然后,测试设备可以提供自己的实现;   有效地使用链接器为我们完成肮脏的工作。

     

在某些圈子中,这被称为“链接缝”。

理论上是的。我们可以以一个简单的案例为例进行演示。

一个简单的程序存在两个类,AB。 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,...A100libB来自类B1,B2,B3,....B100

假设我们要对B3进行单元测试,并且希望A1A2B1B2被模拟。我们该怎么做? 我们需要一个libA without A1,A2libB without B1,B2MockA1MockA2MockB1MockB2吗?

此外,如果B4B5B6都需要做类似B3的事情,这似乎非常复杂。

手动操作很复杂,很容易犯错误并且很难维护。

我不知道如何让链接程序为我们做肮脏的工作?

上面链接中的某人说该技术已被用于实践项目中。但是我学习了很多,却一无所知。

任何已经使用此技术的开源项目链接将非常有帮助。使用CMake或Makefile进行编译对我来说甚至更好。

感谢您的时间。

修改 Mike van Dyke分享了另一种无需虚拟功能即可进行模拟的方法。 该方法可以进行模拟工作,而无需使用链接器。这是进行模拟的另一种解决方案。 Using googlemock with fake impls of non-virtual functions

1 个答案:

答案 0 :(得分:1)

我了解您的情况如下:为了测试B3,您需要真实的B3以及A1A2B1和{{1 }}。您的假设是,您将使用与生产代码类似的库设置:将存在一个包含B2B3B4的库,但肯定没有{{1 }}和B5,因为它们将被嘲笑。

对于单元测试可执行文件,我的建议是选择不同的库设置:创建单独的库B1B2等,并为模拟的libMockA1类创建单独的库。然后,您可以在构建测试可执行文件时更独立地组合它们。为了测试libMockA2,您可以将Bx对象文件与B3B3libMockA1libMockA2链接。为了测试libMockB1,您可以将libMockB2对象文件与B4B4libMockA1等链接起来。

或者,您可以完全放弃使用库进行单元测试,而只单独链接目标文件。

您仍然需要为libMockB1libMockB3类创建模拟,但是您可以为每个测试可执行文件单独组合它们-无需为每个测试创建不同配置的库可执行文件。