有时候,我们需要做模拟测试。最广泛使用的依赖注入(inject)方法是使用模板或接口(interface)。
然而,有时,对于一些遗留代码,存在一些没有虚函数和模板的具体类。由于某些原因,我们不想或不能修改生产代码。但是我们还是想对具体类进行模拟测试。
关于这个话题已经存在很多讨论。大多数人表示,即使不是不可能,也很难做到。
幸运的是,我似乎找到了黎明。
(1) Pavel Minaev 在 Interfaces vs Templates for dependency injection in C++ 中的回答
With C++, there's another option - you give your mock classes exact same names as the real classes, and when linking your unit tests, just link them with mock object/library files instead of real ones.
(2) sdg 在 fake/mock nonvirtual C++ methods 中的回答
One way that we sometimes use is to split the original .cpp file into at least two parts.
Then the test apparatus can supply its own implementations; effectively using the linker to do the dirty work for us.
This is called the "Link Seam" in some circles.
理论上是的。我们可以用一个简单的例子来演示。
一个简单的程序存在两个类,A
和B
。 B是A的用户。
当我们要对B类进行单元测试时,可以在MockA.cpp
中再定义一个A
。并通过以下命令生成单元测试执行文件。
g++ testB.cpp B.cpp MockA.cpp
发布的时候,我们可以通过以下命令生成可执行文件
g++ Main.cpp B.cpp A.cpp
我的问题是我们如何在一个庞大的程序中实现它?
它是一个真实的程序,可能存在很多类并且它们被打包到库中。
例如:一个庞大的程序需要使用两个库。 libA
来自 A1,A2,A3,...A100
类。 libB
来自类 B1,B2,B3,....B100
。
假设我们要对 B3 进行单元测试,我们想要 A1
,A2
,B1
,B2
被 mock 。我们怎么能这样做?
我们需要一个没有A1,A2的libA
,没有B1,B2的libB
,MockA1
,MockA2
, MockB1
,MockB2
?
而且,如果B4
、B5
、B6
都需要做类似B3
的事情,看来非常复杂。
手工操作复杂,容易出错,维护困难。
我不知道如何让链接器为我们做脏活?
上面链接有人说这个技术已经用到实际项目中了。但是我搜索了很多并且没有线索。
任何指向已经使用此技术的开源项目的链接都将非常有帮助。使用 CMake 或 Makefile 编译对我来说会更好理解。
感谢您的宝贵时间。
编辑
Mike van Dyke 分享了另一种不使用虚函数进行模拟的方法。 该方法可以在不使用链接器的情况下使模拟工作。这是制作模拟的另一种解决方案。
最佳答案
我对您的场景的理解如下:用于测试 B3
你需要真正的B3
和模拟A1
, A2
, B1
和 B2
.您的假设是,您将使用与生产代码类似的库设置:将有一个带有 B3
的库。 , B4
, B5
, 但肯定不是 B1
和 B2
,因为这些将被 mock 。
我的建议是,对于单元测试可执行文件,选择不同的库设置:创建单独的库 libMockA1
, libMockA2
等等,以及类似的模拟 Bx
的个人库。类。然后您可以在构建测试可执行文件时更独立地组合它们。用于测试B3
然后您将链接 B3
带有 libMockA1
的目标文件, libMockA2
, libMockB1
和 libMockB2
.用于测试B4
你会链接B4
目标文件,例如 libMockA1
, libMockB1
和 libMockB3
等
或者,您可以完全放弃使用库进行单元测试,而只单独链接目标文件。
您仍然需要为 Ax
创建模拟和 Bx
类,但您随后可以为每个测试可执行文件单独组合它们 - 无需为每个测试可执行文件创建不同配置的库。
关于c++ - 如何在 C++ 中通过链接器进行模拟测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59211988/