如何用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
相关产品推荐
相关产品推荐

