You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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));

这里的逻辑是:

  1. MyFunction(firstStr, _):firstStr会被GMock隐式转换成Eq(firstStr)匹配器,用来验证调用时第一个参数的值是否等于firstStr;_是通配符匹配器,表示第二个参数可以是任意值(我们只关心给它赋值)。
  2. WillOnce(SetArgReferee<1>(test)):直接用SetArgReferee给第二个参数(索引从0开始)赋值为test,这是合法的动作,因为第二个参数是可修改的引用。

为什么你的之前写法都不对?

咱们逐个看:

  1. 第一种写法:DoAll(firstStr, SetArgReferee<1>(test))
    • firstStr是普通字符串,不是GMock支持的动作(比如SetArgReferee、Invoke这些才是动作),所以编译会报错。DoAll的每个参数必须是动作,不能直接放值。
  2. 第二种写法:DoAll(_, SetArgReferee<1>(test))
    • _是匹配器,不是动作,同样不符合DoAll的参数要求,编译错误。
  3. 第三种写法: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:04:50