已声明友元类,仍无法在Google Test TEST_F函数中设置私有成员
问题:TEST_F函数无法访问类私有成员,SetUp()却可以?
我在SetUp()方法里能成功设置并访问privateData,但在TEST_F函数里做同样操作时,代码编译失败,提示函数不可访问。我本来以为通过友元类声明应该允许这种操作,但显然哪里出问题了——是测试fixture配置错了,还是我对C++友元机制理解有误?
相关代码
A.h
#ifndef A_H #define A_H class A { friend class testsA; // Friend class declaration private: int privateData; public: A() : privateData(0) {} private: void setPrivateData(int data) { privateData = data; } int getPrivateData() const { return privateData; } }; #endif // A_H
testsA.h
#ifndef TESTS_A_H #define TESTS_A_H #include "A.h" #include <gtest/gtest.h> class testsA : public testing::Test { public: A* a_instance; // Public member instance of A protected: void SetUp() override { a_instance = new A(); a_instance->setPrivateData(42); // Set private member in SetUp } }; #endif // TESTS_A_H
测试实现文件
#include "testsA.h" TEST_F(testsA, TestPrivateDataSetting) { // Trying to access and set private data in the test case a_instance->setPrivateData(100); ASSERT_EQ(a_instance->getPrivateData(), 100); } TEST_F(testsA, EnsureSetUpValueAccessible) { // This will access the value set in SetUp ASSERT_EQ(a_instance->getPrivateData(), 42); }
原因与解决方法
问题核心是Google Test的TEST_F宏会生成一个继承自你的testsA类的新测试类,而你给A声明的友元仅仅是testsA本身,它的子类(也就是TEST_F生成的类)不在友元列表里,自然无法访问A的私有成员。
而SetUp()是testsA类的成员函数,属于友元类的成员,所以能正常访问A的私有内容。
给你两种可行的解决办法:
方法1:修改友元声明适配GTest的模板机制
把A类里的友元声明改成允许所有testing::Test的子类访问,也就是用模板友元:
class A { // 替换原来的friend class testsA; template <typename T> friend class testing::Test; private: // ... 原有代码不变 };
这样所有基于GTest Test类的测试子类,包括TEST_F生成的类,都能访问A的私有成员了。
方法2:在Fixture中封装私有成员访问接口
不在测试用例里直接操作A的私有方法,而是在testsA类里封装一层公共接口,测试用例调用这些接口即可:
修改testsA.h:
class testsA : public testing::Test { public: A* a_instance; // 封装访问A私有成员的接口 void setAPrivateData(int data) { a_instance->setPrivateData(data); } int getAPrivateData() const { return a_instance->getPrivateData(); } protected: void SetUp() override { a_instance = new A(); setAPrivateData(42); } };
然后修改测试用例:
TEST_F(testsA, TestPrivateDataSetting) { setAPrivateData(100); ASSERT_EQ(getAPrivateData(), 100); } TEST_F(testsA, EnsureSetUpValueAccessible) { ASSERT_EQ(getAPrivateData(), 42); }
这种方法更符合封装原则,也不用修改被测试类A的友元声明。
内容的提问来源于stack exchange,提问作者Sam12
相关产品推荐
相关产品推荐

