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

使用gtest与gmock_global Mock C++类方法中调用的全局函数

解决类方法内部调用的全局函数Mock问题

问题核心:你的测试代码中Mock了全局函数foo(),但Bar::buildBarStr()仍然调用原系统函数,原因是编译链接时Bar类绑定的是原全局foo的符号,而非Mock版本。以下是几种可行的解决方案:

方案一:预处理宏切换实现(无需修改生产代码结构)

在生产代码的foo定义处添加编译宏判断,测试环境下将foo声明为外部符号,让链接器指向Mock版本:

生产代码中修改foo的定义:

#ifndef TEST_BUILD
int foo(){
    return some_sys_parametr;
}
#else
// 测试环境下仅声明foo,由gmock_global提供实现
extern int foo();
#endif

测试代码中添加宏定义:

在测试文件开头或编译选项中添加#define TEST_BUILD,确保编译测试代码时使用Mock的foo:

#define TEST_BUILD
#include "gmock/gmock.h"
#include "gmock_global/gmock_global.h"
#include "Bar.h"

MOCK_GLOBAL_FUNC0(foo, int(void));

TEST_F(FoobBarTest, FooBar)
{
    Bar test_obj;
    ON_GLOBAL_NICE_CALL(foo, foo()).WillByDefault(Return(1));
    EXPECT_GLOBAL_CALL(foo, foo()).Times(2);
    
    std::cout << "Test call ret: " << foo() << std::endl; // 输出1
    std::cout << "Test in obj call: " << test_obj.buildBarStr() << std::endl; // 输出Mock值1
}

方案二:利用Weak符号覆盖(GCC/Clang环境)

将原全局函数foo声明为Weak符号,这样测试代码中Mock的强符号会在链接时覆盖原函数:

生产代码中修改foo的声明:

// 声明为Weak符号,允许被强符号覆盖
__attribute__((weak)) int foo();

int foo(){
    return some_sys_parametr;
}

测试代码无需额外修改,保持你原有的Mock代码即可:

编译测试程序时,链接器会优先使用gmock_global生成的强符号foo,替换原Weak版本,此时Bar::buildBarStr()会调用Mock的foo。

方案三:依赖注入重构(更符合测试设计原则)

如果允许修改生产代码,将全局函数封装为抽象接口,通过依赖注入让Bar类依赖接口而非具体全局函数,这样测试时直接Mock接口即可:

1. 定义抽象接口

class SysParamInterface {
public:
    virtual ~SysParamInterface() = default;
    virtual int getFoo() const = 0;
};

2. 生产环境实现

class RealSysParam : public SysParamInterface {
public:
    int getFoo() const override {
        return some_sys_parametr;
    }
};

// 全局默认实例(兼容原有调用逻辑)
static RealSysParam g_real_sys_param;
SysParamInterface& g_sys_param = g_real_sys_param;

3. 修改Bar类依赖接口

class Bar{
private:
    const SysParamInterface& param_interface_;
public:
    // 构造函数注入,默认使用全局实例
    Bar(const SysParamInterface& param_interface = g_sys_param) 
        : param_interface_(param_interface) {}
    
    std::string buildBarStr(){
        std::string ans;
        int some_param = param_interface_.getFoo();
        // some code
        return ans;
    }
};

4. 测试时Mock接口

#include "gmock/gmock.h"

class MockSysParam : public SysParamInterface {
public:
    MOCK_METHOD(int, getFoo, (), (const, override));
};

TEST_F(FoobBarTest, FooBar)
{
    MockSysParam mock_param;
    Bar test_obj(mock_param);
    
    ON_CALL(mock_param, getFoo()).WillByDefault(Return(1));
    EXPECT_CALL(mock_param, getFoo()).Times(2);
    
    std::cout << "Test in obj call: " << test_obj.buildBarStr() << std::endl; // 输出Mock值1
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:53:15