如何在Google Test中使用C语言回调注册函数?
问题描述
我有一个包含回调函数及其注册函数的C语言文件,需要通过Google Test(GTest)对其进行测试。当前尝试使用静态回调函数,但无法访问测试夹具中的m_value成员变量,希望通过回调将m_value赋值为3,示例代码及测试失败结果如下:
#include <gtest/gtest.h> ///////////////////////////////////////// // 这段代码在C文件中 ///////////////////////////////////////// void (*add)(int a, int b); void RegisterAddCallback(void (*callback)(int a, int b)) { add = callback; } ///////////////////////////////////////// // 我目前的尝试方式 // static int s_value; // static void add_static_callback(int a, int b) // { // s_value = a + b; // } class CallbackTests : public ::testing::Test { public: int m_value; void SetUp() override { m_value = 0; } static void add_static_callback(int a, int b) { // 这里无法访问m_value,但我需要修改它 int value = a + b; } }; TEST_F(CallbackTests, StaticCallback) { RegisterAddCallback(add_static_callback); add(1, 2); EXPECT_EQ(m_value, 3); }
测试失败结果:
Expected equality of these values: m_value Which is: 0 3 [ FAILED ] CallbackTests.StaticCallback (0 ms)
可行实现方法
方法1:全局指针指向当前测试实例(单线程测试适用)
利用全局指针关联当前测试实例,让静态回调通过指针访问非静态成员m_value:
#include <gtest/gtest.h> ///////////////////////////////////////// // 原C文件代码 ///////////////////////////////////////// void (*add)(int a, int b); void RegisterAddCallback(void (*callback)(int a, int b)) { add = callback; } ///////////////////////////////////////// static CallbackTests* g_current_test = nullptr; class CallbackTests : public ::testing::Test { public: int m_value; void SetUp() override { m_value = 0; g_current_test = this; } void TearDown() override { g_current_test = nullptr; } static void add_static_callback(int a, int b) { if (g_current_test != nullptr) { g_current_test->m_value = a + b; } } }; TEST_F(CallbackTests, StaticCallback) { RegisterAddCallback(add_static_callback); add(1, 2); EXPECT_EQ(m_value, 3); }
方法2:线程局部存储(多线程并行测试适用)
将全局指针改为线程局部变量,避免多线程测试时的实例冲突:
#include <gtest/gtest.h> ///////////////////////////////////////// // 原C文件代码 ///////////////////////////////////////// void (*add)(int a, int b); void RegisterAddCallback(void (*callback)(int a, int b)) { add = callback; } ///////////////////////////////////////// static thread_local CallbackTests* g_current_test = nullptr; class CallbackTests : public ::testing::Test { public: int m_value; void SetUp() override { m_value = 0; g_current_test = this; } void TearDown() override { g_current_test = nullptr; } static void add_static_callback(int a, int b) { if (g_current_test != nullptr) { g_current_test->m_value = a + b; } } }; TEST_F(CallbackTests, StaticCallback) { RegisterAddCallback(add_static_callback); add(1, 2); EXPECT_EQ(m_value, 3); }
方法3:修改C代码的回调签名(最优解)
如果允许修改原C代码,给回调添加用户数据参数,彻底摆脱全局变量依赖:
修改后的C代码:
#include <stddef.h> typedef void (*add_callback_t)(int a, int b, void* user_data); static add_callback_t add = nullptr; static void* add_user_data = nullptr; void RegisterAddCallback(add_callback_t callback, void* user_data) { add = callback; add_user_data = user_data; } void CallAdd(int a, int b) { if (add != nullptr) { add(a, b, add_user_data); } }
对应的GTest代码:
#include <gtest/gtest.h> typedef void (*add_callback_t)(int a, int b, void* user_data); void RegisterAddCallback(add_callback_t callback, void* user_data); void CallAdd(int a, int b); class CallbackTests : public ::testing::Test { public: int m_value; void SetUp() override { m_value = 0; } static void add_callback(int a, int b, void* user_data) { CallbackTests* test = static_cast<CallbackTests*>(user_data); test->m_value = a + b; } }; TEST_F(CallbackTests, CallbackWithUserData) { RegisterAddCallback(CallbackTests::add_callback, this); CallAdd(1, 2); EXPECT_EQ(m_value, 3); }
内容的提问来源于stack exchange,提问作者Youngmin Kim
相关产品推荐
相关产品推荐

