基于NVI惯用法的非虚函数Mock问题及解决方案咨询
针对NVI惯用法下Google Test Mock类的编译问题解决方案
在使用NVI(非虚接口)模式设计Communicator抽象类时,公共非虚函数(如Connect)调用私有纯虚函数(如DoConnect)的结构,确实会给Google Test Mock类的编写带来困扰——如果只Mock公共函数,未实现私有纯虚函数会导致Mock类成为抽象类,触发编译错误。针对你列出的四种思路,最优方案如下:
推荐方案:重写私有纯虚函数
这是唯一既保留NVI设计优势,又能正常完成Mock测试的方案。C++允许子类重写基类的私有虚函数(尽管子类无法直接调用这些函数,但基类的公共非虚函数会触发其执行)。具体实现方式是:
- 在
MockCommunicator中重写所有基类的私有纯虚函数; - 为每个重写的纯虚函数定义对应的Google Test Mock方法,在重写函数中调用该Mock方法。
示例代码:
class MockCommunicator : public Communicator { private: // 重写基类的私有纯虚函数 void DoConnect() override { MockDoConnect(); } void DoDisconnect() override { MockDoDisconnect(); } // 定义Google Test Mock方法,用于设置调用期望和验证 MOCK_METHOD(void, MockDoConnect, (), (private)); MOCK_METHOD(void, MockDoDisconnect, (), (private)); };
这种方式既满足了基类对纯虚函数实现的强制要求,又能通过Mock方法完成测试验证,完全保留了NVI模式的封装性、流程控制能力,以及强制子类实现核心逻辑的约束。
其他思路的问题分析
- 将纯虚函数改为普通虚函数:直接破坏了NVI模式强制子类实现核心逻辑的设计初衷,后续新增子类时可能遗漏必要的函数实现,引入维护风险,不推荐。
- 将MockCommunicator设为友元:会打破生产代码的封装性,让测试代码与生产代码耦合度升高,而且Google Test的Mock宏生成的函数通常为公共成员,需要额外适配,得不偿失。
- 放弃NVI惯用法:NVI模式带来的统一流程控制(如参数校验、日志、错误处理)、接口稳定性等优势是测试便利性无法替代的,完全放弃属于因小失大。
内容的提问来源于stack exchange,提问作者İsa Yurdagül
相关产品推荐
相关产品推荐

