如何在GTest DoAll()中处理const输入参数并设置输出参数?
解决GMock模拟带const输入和引用输出函数的问题
首先,咱们先理清你写法里的核心问题:你混淆了GMock里的「匹配器(Matchers)」和「动作(Actions)」,而且DoAll的参数必须是合法的GMock动作,不能直接放普通值或者匹配器。
你的Mock函数MyFunction第一个参数是const std::wstring&(只读输入),第二个是std::wstring&(可写输出)。针对这种场景,正确的做法是:在EXPECT_CALL的参数位置验证输入参数的值,在WillOnce里只处理输出参数的赋值——完全不需要对第一个输入参数做任何「动作」,因为它是只读的,Mock只需要确认它被传入了预期值就行。
正确的写法示例
std::wstring firstStr = L"firstStr"; std::wstring test = L"test"; // 验证第一个参数是firstStr,给第二个输出参数赋值为test EXPECT_CALL(*myGmockInstance, MyFunction(firstStr, _)) .Times(1) .WillOnce(SetArgReferee<1>(test));
这里的逻辑是:
MyFunction(firstStr, _):firstStr会被GMock隐式转换成Eq(firstStr)匹配器,用来验证调用时第一个参数的值是否等于firstStr;_是通配符匹配器,表示第二个参数可以是任意值(我们只关心给它赋值)。WillOnce(SetArgReferee<1>(test)):直接用SetArgReferee给第二个参数(索引从0开始)赋值为test,这是合法的动作,因为第二个参数是可修改的引用。
为什么你的之前写法都不对?
咱们逐个看:
- 第一种写法:
DoAll(firstStr, SetArgReferee<1>(test))firstStr是普通字符串,不是GMock支持的动作(比如SetArgReferee、Invoke这些才是动作),所以编译会报错。DoAll的每个参数必须是动作,不能直接放值。
- 第二种写法:
DoAll(_, SetArgReferee<1>(test))_是匹配器,不是动作,同样不符合DoAll的参数要求,编译错误。
- 第三种写法:
DoAll(SetArgReferee<0>(firstStr), ...)- 第一个参数是
const std::wstring&,SetArgReferee会尝试修改这个参数的值,违反了const限定,所以编译直接报错。
- 第一个参数是
如果需要多个动作怎么办?
如果你的场景确实需要执行多个动作(比如除了设置输出,还要打印日志或者触发其他逻辑),那DoAll里的每个元素都必须是合法的GMock动作,比如:
EXPECT_CALL(*myGmockInstance, MyFunction(Eq(firstStr), _)) .Times(1) .WillOnce(DoAll( // 第一个动作:打印输入参数 Invoke([](const std::wstring& in, std::wstring&) { wprintf(L"Received input parameter: %s\n", in.c_str()); }), // 第二个动作:设置输出参数 SetArgReferee<1>(test) ));
这里的Invoke是GMock的动作,用来执行自定义逻辑,和SetArgReferee一起放在DoAll里,就可以顺序执行多个动作。
内容的提问来源于stack exchange,提问作者beasone
相关产品推荐
相关产品推荐

