我正在尝试模拟一个模板化方法。
这是包含模拟方法的类:
class myClass
{
public:
virtual ~myClass() {}
template<typename T>
void myMethod(T param);
}
如何使用 Google Mock 模拟方法 myMethod?
在以前版本的 Google Mock 中,您只能模拟虚函数,请参阅项目页面中的文档。
更新的版本允许模拟 非虚拟方法,使用他们所谓的 hi-perf 依赖注入。
正如用户@congusbongus 在这个答案下方的评论中所说:
Google Mock 依赖于添加成员变量来支持方法 mocking,由于不能创建模板成员变量,因此无法 mock 模板函数
一种解决方法,Michael Harrington 在 googlegroups 链接 中的评论,是使模板方法专门化,这些方法将调用可以模拟的普通函数。它不能解决一般情况,但可以用于测试。
struct Foo
{
MOCK_METHOD1(GetValueString, void(std::string& value));
template <typename ValueType>
void GetValue(ValueType& value);
template <>
void GetValue(std::string& value) {
GetValueString(value);
}
};
这里再次附上原帖,并附有评论以帮助理解:
struct Foo
{
// Our own mocked method that the templated call will end up calling.
MOCK_METHOD3(GetNextValueStdString, void(const std::string& name, std::string& value, const unsigned int streamIndex));
// If we see any calls with these two parameter list types throw and error as its unexpected in the unit under test.
template< typename ValueType >
void GetNextValue( const std::string& name, ValueType& value, const unsigned int streamIndex )
{
throw "Unexpected call.";
}
template< typename ValueType >
void GetNextValue( const std::string& name, ValueType& value )
{
throw "Unexpected call.";
}
// These are the only two templated calls expected, notice the difference in the method parameter list. Anything outside
// of these two flavors is considerd an error.
template<>
void GetNextValue< std::string >( const std::string& name, std::string& value, const unsigned int streamIndex )
{
GetNextValueStdString( name, value, streamIndex );
}
template<>
void GetNextValue< std::string >( const std::string& name, std::string& value )
{
GetNextValue< std::string >( name, value, 0 );
}
};
这里有一个不需要手动实现每个模板实例化的解决方案,如果有很多不同的模板实例化,这尤其有用。
struct Foo
{
template <typename T>
struct FooImpl
{
MOCK_METHOD(void, myMethod, (const T& value), ());
};
template <typename T>
void myMethod(const T& value)
{
GetMock<T>()->myMethod(value);
}
template <typename T>
std::shared_ptr<FooImpl<T>> GetMock()
{
std::shared_ptr<FooImpl<T>> result;
std::shared_ptr<void> voidValue;
if (!(voidValue = mCachedImpls[typeid(T).name()])
{
result = std::make_shared<FooImpl<T>>();
mCachedImpls[typeid(T).name()] = std::reinterpret_pointer_cast<void>(result);
}
else
{
result = std::reinterpret_pointer_cast<FooImpl<T>>(voidValue);
}
return result;
}
private:
std::unordered_map<std::string, std::shared_ptr<void>> mCachedImpls;
};
然后可以像这样准备模拟:
Foo foo;
EXPECT_CALL(*(foo.GetMock<int>()), myMethod(_)).Times(1);