如何使用GMock模拟返回类型为模板的成员函数?
如何模拟模板成员函数
getVar()? #include <gtest/gtest.h> #include <gmock/gmock.h> #include <memory> #include <iostream> #include <string> using testing::_; using testing::AllOf; using testing::Args; using testing::Return; struct Base { Base() { std::cout << "Base constructed" << std::endl; } }; struct Foo { template <typename T> T* getVar() { return new T; // 忽略内存泄漏,仅用于测试 } }; struct Bar { Bar(Foo& f) : f(f) {} virtual void testFoo() { f.getVar<Base>(); } Foo f; }; struct FooMock : public Foo { // 如何模拟getVar()? }; struct TestBar : public Bar, public ::testing::Test { TestBar() : Bar(f) {} FooMock f; }; TEST_F(TestBar, TestCase) { testFoo(); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
如何模拟
getVar()函数?该函数的返回类型为模板类型。我无法让MOCK_METHOD宏适配模板类型,也不知道如何将该函数纳入宏中使用。我希望完全避免为了模拟而重写getVar()函数。补充说明:若采用高性能依赖注入方案,忽略原函数缺少
virtual修饰的问题,该如何使用MOCK_METHOD模拟这个返回类型为模板的成员函数?
核心问题说明
C++不支持虚函数模板,而Google Mock的MOCK_METHOD宏依赖虚函数实现多态模拟,因此无法直接Mock模板成员函数。我们可以通过针对测试用到的模板实例手动桥接Mock函数,结合高性能依赖注入(模板参数注入)来实现需求。
解决方案1:针对特定模板实例桥接Mock函数
如果测试中仅用到getVar<Base>这类特定实例,可在FooMock中定义普通Mock函数,再通过模板特化将原模板函数桥接到Mock函数:
struct FooMock : public Foo { // 定义用于Mock的普通成员函数 MOCK_METHOD(Base*, getVarBase, ()); }; // 在类外部特化getVar<Base>,桥接到Mock函数 template<> Base* FooMock::getVar<Base>() { return getVarBase(); }
测试用例中设置期望:
TEST_F(TestBar, TestCase) { EXPECT_CALL(f, getVarBase()) .WillOnce(Return(new Base())); testFoo(); }
解决方案2:高性能依赖注入(无虚函数)
若要避免虚函数开销,可将Bar改为模板类,通过模板参数注入Foo或FooMock,结合上述桥接方式实现Mock:
- 修改
Bar为模板类:
template<typename FooImpl> struct Bar { Bar(FooImpl& f) : f(f) {} void testFoo() { f.getVar<Base>(); } FooImpl& f; };
- 调整测试类:
struct TestBar : public ::testing::Test { FooMock f; Bar<FooMock> bar{f}; };
- 测试用例中设置期望:
TEST_F(TestBar, TestCase) { EXPECT_CALL(f, getVarBase()) .WillOnce(Return(new Base())); bar.testFoo(); }
注意事项
- 模板特化必须在命名空间级别(类外部)实现,不能在类内部直接特化模板成员函数。
- 若需要Mock多个不同的模板实例(如
getVar<int>、getVar<std::string>),只需为每个实例添加对应的Mock函数和特化即可。
内容的提问来源于stack exchange,提问作者davidj361
相关产品推荐
相关产品推荐

