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

如何用Google Test测试返回void类型的函数?

测试修改全局变量的Void函数(Google Test方案)

针对你遇到的无返回值、仅修改全局变量的函数测试需求,除了实现fake函数外,还有以下几种更易维护的测试方案:

方法1:封装全局变量为访问接口

将全局变量的访问封装成专用getter(必要时加setter/resetter),让测试代码通过接口而非直接引用全局变量,彻底解耦测试与变量名的绑定。

修改生产代码(低侵入性)

// target_code.h
void add_num(int n);
int get_current_number(void); // 新增获取接口
void reset_number(void);      // 新增重置接口(用于测试前置清理)

// target_code.c
#include "target_code.h"

// 将全局变量改为static,禁止外部直接访问
static int number = 0;

void add_num(int n) {
    number += n;
}

int get_current_number(void) {
    return number;
}

void reset_number(void) {
    number = 0;
}

Google Test测试代码

#include <gtest/gtest.h>
#include "target_code.h"

TEST(AddNumTest, PositiveNumberAddition) {
    reset_number();
    add_num(5);
    EXPECT_EQ(get_current_number(), 5);
    add_num(3);
    EXPECT_EQ(get_current_number(), 8);
}

TEST(AddNumTest, NegativeNumberAddition) {
    reset_number();
    add_num(-2);
    EXPECT_EQ(get_current_number(), -2);
    add_num(7);
    EXPECT_EQ(get_current_number(), 5);
}

优势:就算后续生产代码中全局变量名修改,只要保持接口不变,测试代码无需改动;同时static修饰全局变量还能减少外部命名污染。

方法2:重构为状态对象(依赖注入思路)

如果允许对生产代码做结构重构,把全局状态封装成局部对象,让函数操作对象而非全局变量,测试时可独立创建实例,完全避免全局状态污染。

修改生产代码(面向对象重构)

// target_code.h
typedef struct {
    int count;
} Counter;

// 初始化计数器
void counter_init(Counter* counter);
// 执行加法操作
void counter_add(Counter* counter, int n);

// target_code.c
#include "target_code.h"

void counter_init(Counter* counter) {
    counter->count = 0;
}

void counter_add(Counter* counter, int n) {
    counter->count += n;
}

Google Test测试代码

#include <gtest/gtest.h>
#include "target_code.h"

TEST(CounterTest, BasicAddition) {
    Counter counter;
    counter_init(&counter);
    
    counter_add(&counter, 10);
    EXPECT_EQ(counter.count, 10);
    
    counter_add(&counter, -4);
    EXPECT_EQ(counter.count, 6);
}

TEST(CounterTest, MultipleInstances) {
    Counter counter1, counter2;
    counter_init(&counter1);
    counter_init(&counter2);
    
    counter_add(&counter1, 3);
    counter_add(&counter2, 7);
    
    EXPECT_EQ(counter1.count, 3);
    EXPECT_EQ(counter2.count, 7);
}

优势:测试用例完全独立,无需担心全局状态残留;代码结构更清晰,扩展性更强。

方法3:链接时劫持全局变量(无侵入生产代码)

如果无法修改生产代码,可利用链接器的符号优先级,在测试代码中定义同名全局变量,覆盖生产代码中的变量,实现测试时的状态控制。

Google Test测试代码

#include <gtest/gtest.h>
#include "target_code.h"

// 定义与生产代码同名的全局变量,链接时会优先使用该版本
int number = 0;

TEST(AddNumTest, GlobalVariableModification) {
    // 测试前手动重置状态
    number = 0;
    add_num(15);
    EXPECT_EQ(number, 15);
    
    add_num(-5);
    EXPECT_EQ(number, 10);
}

注意:需确保测试代码的链接顺序优先于生产代码(比如编译时先编译测试文件再链接生产代码),否则无法覆盖原变量。这种方式适合遗留系统的临时测试,但变量名修改后测试代码仍需同步调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 13:15:30