Google Mock模板Mock类EXPECT_CALL报错及解决方案咨询
Google Mock调用Mock方法时出现"has no member named gmock_xxx"错误
我的代码背景
首先我定义了这样一个模板Mock类:
template<typename T> class ParseTreeMock : public ParseTreeInterface<T> { public: MOCK_METHOD1(fillConfigTree, void(std::string const&)); MOCK_METHOD1_T(getProperty, T(std::string const&)); ParseTreeMock(): parseTree(std::make_unique<pt::ptree>()) { } static std::unique_ptr<ParseTreeInterface<T>> getDefaultTree() { return std::make_unique<ParseTreeMock<T>>(); } private: std::unique_ptr<pt::ptree> parseTree; };
然后在测试用例中创建Mock对象:
class ConfigTest : public ::testing::Test { protected: std::unique_ptr<ParseTreeInterface<std::string>> treeMock; virtual void SetUp() { treeMock = ParseTreeMock<std::string>::getDefaultTree(); } };
当我尝试为getProperty方法设置指定返回值时:
EXPECT_CALL(*treeMock, getProperty("miniReaderConfig.cacheConfig.cacheOnOff")) .willOnce(Return(false));
出现了编译错误:
In file included from ./lib/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h:43:0, from ./lib/googletest/googlemock/include/gmock/gmock.h:61, from ./test/UT/Mocks/ParseTreeMock.hpp:2, from test/UT/Configuration/ConfigTest.cpp:1: test/UT/Configuration/ConfigTest.cpp: In member function ‘virtual void ConfigTest_CreateConfigurationWithoutErrors_Test::TestBody()’ ./lib/googletest/googlemock/include/gmock/gmock-spec-builders.h:1844:12: error: ‘class miniReader::Configuration::ParseTreeInterface<std::__cxx11::basic_string<char> >’ has no member named ‘gmock_getProperty’ did you mean ‘getProperty’ ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
错误原因分析
这个错误的核心是静态类型不匹配:
treeMock的静态类型是基类ParseTreeInterface<std::string>的智能指针,而Google Mock在生成Mock类时,会自动为每个MOCK_METHOD生成对应的gmock_xxx辅助成员函数(比如这里的gmock_getProperty),这些成员只存在于派生的ParseTreeMock类中,基类ParseTreeInterface里根本没有这些扩展方法。- 当你用
*treeMock调用EXPECT_CALL时,编译器只能识别到基类的类型,自然找不到只有Mock子类才有的gmock_getProperty方法,于是抛出了这个错误。
解决方案
这里有两种可行的解决方法,你可以根据代码结构需求选择:
方法1:修改测试类中Mock对象的类型为Mock子类
把treeMock的类型从基类指针改成ParseTreeMock<std::string>的智能指针,让编译器直接看到Mock类的所有成员。修改后的测试类代码如下:
class ConfigTest : public ::testing::Test { protected: // 改成Mock子类的智能指针 std::unique_ptr<ParseTreeMock<std::string>> treeMock; virtual void SetUp() { // 因为getDefaultTree返回基类指针,需要做类型转换 treeMock = std::static_pointer_cast<ParseTreeMock<std::string>>( ParseTreeMock<std::string>::getDefaultTree() ); // 或者更简单:直接创建Mock对象,跳过getDefaultTree // treeMock = std::make_unique<ParseTreeMock<std::string>>(); } };
如果可以的话,也可以修改getDefaultTree的返回类型为std::unique_ptr<ParseTreeMock<T>>,这样就不需要额外的类型转换了。
方法2:在EXPECT_CALL时显式转换为Mock子类指针
如果不想修改测试类中成员变量的类型,可以在设置期望的时候,把基类指针强制转换为Mock子类的指针:
EXPECT_CALL(*static_cast<ParseTreeMock<std::string>*>(treeMock.get()), getProperty("miniReaderConfig.cacheConfig.cacheOnOff")) .willOnce(Return(false));
这种方法适合需要保持基类指针接口的场景,但每次设置期望都要做转换,相对麻烦一点。
内容的提问来源于stack exchange,提问作者Temple
相关产品推荐
相关产品推荐

