如何用旧版gmock模拟被派生类重载的基类虚方法?
问题描述
我正尝试使用旧版gmock模拟基类的一个虚方法,该方法实现了一些基础功能,且被派生类的重载版本调用。
我编写的代码如下:
class BaseFoo { public: virtual bool init() { std::cout << "Some basic functionality" << std::endl; return true; } }; class Foo : public BaseFoo { public: bool init() override { if (!BaseFoo::init()) return false; std::cout << "Some additional functionality" << std::endl; return true; } }; class MockFoo : public Foo { public: MOCK_METHOD0(BaseFoo::init, bool()); }; TEST(FooTests, InitTest) { Foo f; bool result = false; EXPECT_CALL(f, BaseFoo::init).WillOnce(testing::Return(true)); result = f.init(); ASSERT_TRUE(result); }
运行后遇到的错误:
error: cannot define member function 'BaseFoo::init' within 'MockFoo' MOCK_METHOD0(BaseFoo::init, bool()); ^ error: 'gmock_BaseFoo' has not been declared MOCK_METHOD0(BaseFoo::init, bool()); ^ error: 'gmock0_BaseFoo' has not been declared MOCK_METHOD0(BaseFoo::init, bool()); ^ error: conflicting return type specified for 'virtual testing::internal::MockSpec<bool()>& MockFoo::init()' MOCK_METHOD0(BaseFoo::init, bool()); ^ error: overriding 'virtual bool Foo::init()' bool init() override ^ error: 'gmock0_BaseFoo' has not been declared MOCK_METHOD0(BaseFoo::init, bool()) ^ error: 'gmock0_BaseFoo' has not been declared MOCK_METHOD0(BaseFoo::init, bool()); ^ error: 'Foo::gmock_BaseFoo' has not been declared EXPECT_CALL(f, BaseFoo::init).WillOnce(testing::Return(true)); ^
我的目标是模拟该基类方法,以便在测试中能够预期它的调用。请问是否有可行的实现方式?
可行实现方式
方法1:重构Foo为模板类,替换基类为Mock版本
通过将Foo改为模板类,测试时可替换其基类为Mock版本,从而捕获基类init()的调用:
// 重构Foo为模板类,默认使用原BaseFoo template<typename Base = BaseFoo> class Foo : public Base { public: bool init() override { if (!Base::init()) return false; std::cout << "Some additional functionality" << std::endl; return true; } }; // 定义BaseFoo的Mock类 class MockBaseFoo : public BaseFoo { public: MOCK_METHOD0(init, bool()); }; // 测试用例 TEST(FooTests, InitTest) { Foo<MockBaseFoo> f; bool result = false; EXPECT_CALL(f, init()).WillOnce(testing::Return(true)); result = f.init(); ASSERT_TRUE(result); }
这种方式无需修改原有业务逻辑的核心,仅通过模板化实现测试时的基类替换。
方法2:在MockFoo中重写init,转发到Mock方法
如果无法修改原Foo结构,可在MockFoo中重写init(),将对BaseFoo::init()的调用替换为Mock方法:
class MockFoo : public Foo { public: // 定义模拟基类init的Mock方法 MOCK_METHOD0(mock_base_init, bool()); bool init() override { // 用Mock方法替代原BaseFoo::init() if (!mock_base_init()) return false; // 保留Foo原本的额外逻辑 std::cout << "Some additional functionality" << std::endl; return true; } }; TEST(FooTests, InitTest) { MockFoo f; bool result = false; EXPECT_CALL(f, mock_base_init()).WillOnce(testing::Return(true)); result = f.init(); ASSERT_TRUE(result); }
该方案无需改动原业务代码,仅通过Mock类的重写逻辑实现调用预期。
错误原因说明
原代码的核心问题:
MOCK_METHOD0(BaseFoo::init, bool())写法错误:gmock的Mock宏仅能声明当前类的成员方法,不能直接指定基类方法名。- 测试用例使用了普通
Foo对象而非MockFoo对象:只有Mock类实例才能被EXPECT_CALL捕获调用。
内容的提问来源于stack exchange,提问作者Tailwhip
相关产品推荐
相关产品推荐

