使用gtest将所有方法声明为virtual以进行mocking

Declare all methods virtual for mocking using gtest?

本文关键字:virtual mocking 声明 gtest 有方法 使用      更新时间:2023-10-16

目前我正试图在我的C++项目中使用Google Mock框架(gtest)实现一些基本的Mock。然而,这个框架并不能很好地处理非虚拟方法,这需要一些(至少IMHO)丑陋的解决方案(使用模板)。当然,一个简单的解决方案是简单地使每个方法都是虚拟的,但该框架建议不要这样做,这也不是我真正喜欢的解决方案。

所以,我开始思考,难道没有一种方法可以在不更改实际源文件的情况下,为测试声明每个方法都是虚拟的吗?这可以是一个传递给编译器的标志,也可以是一些CPP voodoo。如果这确实是可能的,那么这种解决方案的缺点是什么?

模拟非虚拟函数的任何其他方式(最好使用gtest/gmock)也值得赞赏。

如果相关的话,我现在正在使用GCC和X-Code。

只有两种方法可以获得虚拟函数:

  • 将其声明为虚拟

  • (从具有相同名称、相同签名、虚拟函数的基类继承)

第一个可以显式完成,也可以通过宏完成,但这会导致代码难看。第二个可以使用模板库来完成,它通常默认为空,但为了测试目的,您可以使用一个类来实例化它,该类镜像您的接口,但声明函数为虚拟的。

struct Empty { };
template <class BaseT = Empty>
class YourClass : public BaseT {
public:
void foo();
};

有争议但足以表明意图。您可以使用上面的代码进行普通的、非虚拟的使用。然后,对于您的测试:

struct YourClassTester {
virtual void foo() = 0;
virtual ~YourClassBase() { }
};
YourClass<YourClassTester> testable;

等等。当然,这确实意味着你测试的代码与实际使用的代码不同,而且可能存在可检测的差异,例如:

  • 类大小较大(vtbl)

  • 存储器布局不同的

  • RTTI支持在测试中有效,在生产中无效

  • 根据原始类别(is_standard_layout、is_pod、is_trivialy_copyable等),一些类型特征的结果也可能不同

如果这些都无关紧要,并且您不介意将类作为模板,那么您可以尝试这种方法。