首页 > 解决方案 > 使用预处理器模拟非虚拟方法

问题描述

我正在使用 C++ 开发一个嵌入式项目,其中资源有点有限。这意味着除非我真的需要它们,否则我会尽量小心使用过多的虚拟方法。我计划开始使用 Gtest 实施单元测试。

因为项目的代码量不算太大,所以大部分代码都是直接写在头文件中的。唯一的惩罚是编译时间多一点。因为编译需要大约 20 秒,所以这不是问题,而且我认为使代码更易于编写/阅读。

如果项目在 Windows 中运行,我将全力以赴创建新的抽象层(或添加接缝类)并在需要它们进行单元测试的地方拥有更多的虚拟方法。由于项目的性质,我不想仅仅为了单元测试的目的而添加额外的虚拟方法。我认为这样做是有效的,但在资源稀缺时似乎有点不合理。

该项目运行良好,并且可以进行单元测试,因此我希望将代码修改保持在最低限度。该问题的解决方案之一是使用“高性能依赖注入”对模板进行一些技巧。这对我来说似乎是鸭式打字,并且仍然需要修改使用该类的原始源代码。

我在想为什么不只使用预处理器:

#ifdef TEST
#define TESTABLE virtual
#else
#define TESTABLE
#endif

然后,当需要模拟一个方法时,您总是可以修改该类的原始源代码并编写如下内容:

TESTABLE void somePreviouslyUnmockeableMethod(void);

我知道其中一个缺点是我现在有两个源代码,一个用于生产,一个用于测试。当一个人决定在单元测试时使用 Mock 类而不是真实类时,无论如何都会发生同样的情况。如果代码更改相当大,那么预处理器的更改可能是一个真正的问题,但我认为通过这个定义,它们被保持在最低限度。

这是一个有效的解决方案吗?我可能忽略了一些负面后果吗?

请注意,所有模块都已经包含一个可以轻松添加定义的ProjectSettings.h文件。TESTABLE

标签: c++mockingembeddedgoogletest

解决方案


如果使类虚拟化真的太昂贵(即您测量这将是太多的开销),您可以使用高性能依赖注入技术。成本只是更长的编译时间,但没有运行时开销。在生产中,您使用真实对象和测试实例化您的类 - 使用具有与真实类相同签名的方法的模拟类。


推荐阅读