如何用gmock模拟依赖类的DB调用以测试test3的testFunction?
解决遗留代码中Test3单元测试的GMock依赖问题
核心问题定位
你遇到的问题本质是遗留代码的依赖硬编码:Test2构造时直接new Test1并调用带DB的initTest1(),没有预留依赖替换的入口,导致你写的MockTest1无法被注入到依赖链中。下面是几种从易到难的解决方案,优先推荐最小侵入式的依赖注入改造。
方案1:给Test2添加依赖注入入口(最稳妥)
对Test2做最小改动,新增支持自定义Test1实例的构造/工厂方法,同时保留原有逻辑兼容旧代码:
改造Test2类
class Test2 { private: Test1* test1; // 私有构造,用于接收自定义Test1实例 explicit Test2(Test1* custom_test1) : test1(custom_test1) { if (test1) { test1->initTest1(); // 保留原有初始化逻辑 } } public: // 原有无参构造,兼容旧业务逻辑 Test2() : Test2(new Test1()) {} // 测试专用工厂方法,注入MockTest1 static Test2* create_for_test(Test1* mock_test1) { return new Test2(mock_test1); } // 如果Test2是单例,修改单例获取逻辑支持注入 static Test2& get_instance(Test1* custom_test1 = nullptr) { static Test2* instance = nullptr; if (!instance) { instance = custom_test1 ? new Test2(custom_test1) : new Test2(); } return *instance; } // ... 原有其他方法 };
编写MockTest1
确保Test1的initTest1是虚函数(如果不是,必须改成虚函数,这是GMOCK覆盖成员函数的前提):
#include <gmock/gmock.h> class MockTest1 : public Test1 { public: MOCK_METHOD(void, initTest1, (), (override)); };
测试用例编写
在测试的SetUp阶段注入MockTest1,替换Test2的单例实例:
TEST(Test3Suite, TestFunction) { // 创建Mock并设置预期行为 auto mock_test1 = std::make_unique<MockTest1>(); EXPECT_CALL(*mock_test1, initTest1()) .Times(1); // 根据实际需求调整调用次数 // 初始化Test2单例时注入Mock Test2& test2_instance = Test2::get_instance(mock_test1.release()); // 现在创建Test3,会使用带Mock的Test2单例 Test3 test3; // 执行待测试方法 test3.testFunction(); // 验证Mock预期是否达成 Mock::VerifyAndClearExpectations(mock_test1.get()); }
方案2:测试隔离单例(避免跨测试污染)
因为单例的生命周期是全局的,每个测试用例结束后需要重置单例,避免影响后续测试:
class Test3Test : public ::testing::Test { protected: void TearDown() override { // 重置Test2的单例指针(需要Test2提供重置接口,或者用友元/全局变量修改,视代码权限而定) Test2::reset_instance(); } }; TEST_F(Test3Test, TestFunction) { // 同方案1的测试逻辑 }
方案3:链接时替换(极端无修改权限时用)
如果完全不能修改Test2/Test1代码,可以用链接时替换技术,将Test1的实现替换为Mock版本:
- 把MockTest1的实现编译成独立目标文件
- 测试编译时,优先链接这个Mock目标文件,覆盖真实的Test1实现
注意:这种方法风险高,容易导致其他测试用例异常,仅作为最后手段。
关键注意事项
- 必须确保Test1的
initTest1是虚函数,否则GMOCK无法正确覆盖该方法 - 单例测试一定要做隔离,否则前一个测试的单例状态会污染后续测试
内容的提问来源于stack exchange,提问作者shans
相关产品推荐
相关产品推荐

