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

标签 c++ unit-testing linker mocking

有时候,我们需要做模拟测试。最广泛使用的依赖注入(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.

理论上是的。我们可以用一个简单的例子来演示。

一个简单的程序存在两个类,AB。 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, MockB1MockB2

而且,如果B4B5B6都需要做类似B3的事情,看来非常复杂。

手工操作复杂,容易出错,维护困难。

我不知道如何让链接器为我们做脏活?

上面链接有人说这个技术已经用到实际项目中了。但是我搜索了很多并且没有线索。

任何指向已经使用此技术的开源项目的链接都将非常有帮助。使用 CMake 或 Makefile 编译对我来说会更好理解。

感谢您的宝贵时间。

编辑

Mike van Dyke 分享了另一种不使用虚函数进行模拟的方法。 该方法可以在不使用链接器的情况下使模拟工作。这是制作模拟的另一种解决方案。

Using googlemock with fake impls of non-virtual functions

最佳答案

我对您的场景的理解如下:用于测试 B3你需要真正的B3和模拟A1 , A2 , B1B2 .您的假设是,您将使用与生产代码类似的库设置:将有一个带有 B3 的库。 , B4 , B5 , 但肯定不是 B1B2 ,因为这些将被 mock 。

我的建议是,对于单元测试可执行文件,选择不同的库设置:创建单独的库 libMockA1 , libMockA2等等,以及类似的模拟 Bx 的个人库。类。然后您可以在构建测试可执行文件时更独立地组合它们。用于测试B3然后您将链接 B3带有 libMockA1 的目标文件, libMockA2 , libMockB1libMockB2 .用于测试B4你会链接B4目标文件,例如 libMockA1 , libMockB1libMockB3

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

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

关于c++ - 如何在 C++ 中通过链接器进行模拟测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59211988/

相关文章:

c++ - 每次我从另一个 C++ 类调用类函数时,我的程序都会崩溃

android - 纠结谷歌测试

php - 未使用 phpUnit 测试异常?

c++ - OpenSSL 1.0.1f 和 "undefined reference to symbol ' SSL_state@@OPENSSL_1.0.0"

c++ - 当我链接到的静态库中清楚地显示符号时,为什么我会收到链接错误?

c++ - 检查字符串的两端均不起作用

c++ - 保留指向前一个循环值的指针?

c++ - 使用 C++20 的 std::popcount 和 vector 优化是否等同于 popcnt 内在?

java - @Spy 在两个列表上注释时不起作用

c++ - 在 64 位机器上从源代码构建 32 位 mysql c++ 连接器