【问题标题】:How to do mock test via linker in C++如何通过 C++ 中的链接器进行模拟测试
【发布时间】:2020-03-31 09:05:47
【问题描述】:

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

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

已经有很多关于这个话题的讨论。大多数人说,即使不是不可能,也很难做到。

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

(1) Pavel Minaev 在Interfaces vs Templates for dependency injection in C++ 中的回答

使用 C++,还有另一种选择 - 您为模拟类指定与真实类完全相同的名称,并且在链接单元测试时,只需将它们与模拟对象/库文件而不是真实文件链接。

(2) sdg 在fake/mock nonvirtual C++ methods的回答

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

然后测试设备可以提供自己的实现;有效地使用链接器为我们做脏活。

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

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

一个简单的程序存在两个类,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。我们怎么能这样做?

我们需要libA without A1,A2libB without B1,B2MockA1MockA2MockB1MockB2

更进一步,如果B4,B5,B6都需要做B3之类的事情,看起来很复杂。

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

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

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

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

感谢您的宝贵时间。

编辑

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

Using googlemock with fake impls of non-virtual functions

【问题讨论】:

标签: c++ unit-testing linker mocking


【解决方案1】:

我对您的情况的理解如下:为了测试B3,您需要真实的B3A1A2B1B2 的模拟。您的假设是,您将使用与生产代码类似的库设置:将有一个带有 B3B4B5 的库,但肯定不是带有 B1B2,因为这些应该被嘲笑。

我的建议是,对于单元测试可执行文件,选择不同的库设置:创建单独的库 libMockA1libMockA2 等,同样为模拟的 Bx 类创建单独的库。然后,您可以在构建测试可执行文件时更独立地组合它们。为了测试B3,您可以将B3 目标文件与libMockA1libMockA2libMockB1libMockB2 链接。为了测试B4,您可以将B4 目标文件与libMockA1libMockB1libMockB3 等链接起来。

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

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

【讨论】:

  • 感谢您的建议。这是解决方案,但似乎很难实施。如果我有所有类 Ax 和 Bx 到 ibrary,我将有太多的库,此外我应该选择测试可执行文件需要哪个库。这似乎导致难以维护。如果以后类关系重组,可执行链接策略也应该改变。
猜你喜欢
  • 2015-07-28
  • 2019-05-23
  • 2021-08-26
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
相关资源
最近更新 更多