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

如何用GMock捕获const char*类型Mock函数参数?有无更简便方法?

GMock捕获const char*参数的简化方案

问题描述

我需要Mock函数http_post的第二个const char*类型参数,用来构建JSON并验证指定元素的值。目前用定义http_post_args结构体结合GMock的Invoke方法实现了需求,但过程繁琐。之前试了SaveArgPointee只复制了字符串首字符,用ACTION_P时没法正确获取参数,对ACTION_TEMPLATE也没搞懂。想问这种结构体方法是不是唯一可行的?能不能给个用ACTION_P或ACTION_TEMPLATE捕获const char*的可行示例?

相关代码

Mock类定义:

class web_api_mock : public iweb_api
{
public:
    MOCK_METHOD(
            (bool), 
            http_post, 
            (const etl_normal_string &, const char*), 
            (override));

};

现有实现代码:

struct http_post_args
{
    void capture(etl_normal_string url, const char * p)
    {
        payload = std::string(p);
    }

    std::string payload;
};

http_post_args args;

EXPECT_CALL(_web_api_mock, http_post(etl_string_equals(url), _))
    .WillOnce(
        DoAll(
            Invoke(&args, &http_post_args::capture),
            Return(true)));

尝试过的ACTION_P代码:

ACTION_P2(capture_string, url, payload) 
{ 
    /* 调试时上层栈帧可见目标字符串,但此处无法访问 */
}

解决方案

结构体+Invoke不是唯一方案,ACTION_P和ACTION_TEMPLATE都能实现更简洁的参数捕获,问题出在你之前的ACTION写法有误。

方法一:用ACTION_P捕获指定参数

GMock的ACTION宏内部可以通过arg0、arg1等内置变量直接访问Mock函数的参数(按声明顺序索引,从0开始)。正确的写法是把存储捕获结果的变量作为ACTION的参数传入,而非把要捕获的参数作为模板参数:

// 定义ACTION_P:接收一个std::string引用,用来存储捕获到的payload
ACTION_P(SavePayload, target_str) {
    // arg1对应http_post的第二个参数(const char*类型)
    target_str = std::string(arg1);
}

// 使用示例
std::string captured_payload;
EXPECT_CALL(_web_api_mock, http_post(etl_string_equals(url), _))
    .WillOnce(DoAll(
        SavePayload(std::ref(captured_payload)), // 必须用std::ref传递引用,避免值拷贝
        Return(true)
    ));

// 后续即可用captured_payload构建JSON并验证元素

方法二:用ACTION_TEMPLATE实现通用参数捕获

如果需要灵活捕获任意位置的参数,ACTION_TEMPLATE是更通用的选择,它支持通过模板参数指定参数索引:

// 定义ACTION_TEMPLATE:模板参数指定要捕获的参数索引,值参数指定存储目标的指针
ACTION_TEMPLATE(SaveNthArg,
                HAS_2_TEMPLATE_PARAMS(int, kArgIndex, typename, T),
                AND_1_VALUE_PARAMETER(target)) {
    // args是Mock函数的参数元组,std::get<kArgIndex>取出对应位置的参数
    *target = std::string(std::get<kArgIndex>(args));
}

// 使用示例:捕获第二个参数(索引为1)
std::string captured_payload;
EXPECT_CALL(_web_api_mock, http_post(etl_string_equals(url), _))
    .WillOnce(DoAll(
        SaveNthArg<1>(&captured_payload),
        Return(true)
    ));

为什么SaveArgPointee会失败?

SaveArgPointee<1>(&captured_payload)的行为是直接复制参数的解引用值:对于const char* p,它会复制*p(即字符串的第一个字符),而非整个字符串。因此要捕获完整字符串,必须手动将const char*转换为std::string,这也是上述ACTION实现中必须做的步骤。


内容的提问来源于stack exchange,提问作者bas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:35:36