c++ - 如何通过 C++ 中的链接器进行模拟测试
问题描述
有时,我们需要做模拟测试。进行依赖注入最广泛使用的方法是使用模板或接口。
然而,有时,对于一些遗留代码,存在一些没有虚函数和模板的具体类。出于某种原因,我们不想或不能修改生产代码。但是我们仍然想对具体类进行模拟测试。
已经有很多关于这个话题的讨论。大多数人说,即使不是不可能,也很难做到这一点。
幸运的是,我似乎找到了曙光。
(1) Pavel Minaev 在Interfaces vs Templates for dependency injection in C++ 中的回答
使用 C++,还有另一种选择——你给你的模拟类赋予与真实类完全相同的名称,并且在链接你的单元测试时,只需将它们与模拟对象/库文件而不是真实的链接。
(2) sdg 在fake/mock nonvirtual C++ 方法中的回答
我们有时使用的一种方法是将原始 .cpp 文件拆分为至少两个部分。
然后测试设备可以提供自己的实现;有效地使用链接器为我们做脏活。
这在某些圈子中被称为“链接缝”。
理论上是的。我们可以以一个简单的案例为例进行演示。
一个简单的程序存在两个类,A
和B
。B 是 A 的用户。
当我们想要对 B 类进行单元测试时。我们可以A
在MockA.cpp
. 并通过以下命令生成单元测试执行文件。
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,A2
, libB without B1,B2
, MockA1
, MockA2
, MockB1
, MockB2
?
此外,如果B4
, B5
,B6
都需要做类似的事情B3
,这似乎很复杂。
手动操作很复杂,很容易出错,很难维护。
我不知道如何让链接器为我们做这些脏活?
上面链接中有人说该技术已经用于实践项目。但是我搜索了很多并且没有线索。
任何指向已经使用此技术的开源项目的链接都将非常有帮助。使用 CMake 或 Makefile 编译对我来说会更好理解。
谢谢你的时间。
编辑
Mike van Dyke 分享了另一种在没有虚函数的情况下进行模拟的方法。该方法可以在不使用链接器的情况下进行模拟工作。这是制作模拟的另一种解决方案。
解决方案
我对您的情况的理解如下:对于测试,您需要、和的B3
真实B3
和模拟。您的假设是,您将使用与生产代码类似的库设置:将有一个带有, ,的库,但肯定不会带有and ,因为这些将被模拟。A1
A2
B1
B2
B3
B4
B5
B1
B2
我的建议是,对于单元测试可执行文件,选择不同的库设置:创建单独的库libMockA1
等libMockA2
,以及类似地为模拟Bx
类创建单独的库。然后,您可以在构建测试可执行文件时更独立地组合它们。为了进行测试,您可以使用、和B3
链接B3
目标文件。为了进行测试,您可以将目标文件与例如 、和等链接起来。libMockA1
libMockA2
libMockB1
libMockB2
B4
B4
libMockA1
libMockB1
libMockB3
或者,您可以完全放弃使用库进行单元测试,而只单独链接目标文件。
您仍然需要为Ax
和Bx
类创建模拟,但您可以为每个测试可执行文件单独组合它们 - 无需为每个测试可执行文件创建不同配置的库。
推荐阅读
- python - 来自 caer.preprocess_from_dir 的详细标志错误
- python-3.x - Python GTK3 - 搜索后以编程方式在TreeView中选择节点?
- reactjs - JSX 道具不应该使用函数 react/jsx-no-bind
- r - 如何使用 distill 更改 R 博客的预览图像布局
- android - 如何解决flutter config --android studio期间出现的问题?
- flask - 如何使用 WTForms 单独渲染单选按钮?
- javascript - 如何在嵌套数组中使用嵌套循环
- laravel - Laravel docker API 路由不工作,但网络路由工作
- python-3.x - 如何将单元格样式从多个输入 xlsx 文件复制到具有多个工作表的多个输出 xlsx 文件
- c# - 我可以使用多线程和并行编程进行网络抓取吗?