ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何用 FRIEND_TEST 在 GoogleTest 中测试 C++ 类的私有成员

如何用 FRIEND_TEST 在 GoogleTest 中测试 C++ 类的私有成员 如何用 FRIEND_TEST 在 GoogleTest 中测试 C 类的私有成员【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest当被测类的关键逻辑位于private或protected区域而你又确实在用 GoogleTest 编写单元测试时直接调用私有成员会编译失败。GoogleTest 提供的FRIEND_TEST宏就是为此设计的在类的定义体内声明一条宏把某个具体的TEST或TEST_F实例声明为该类的友元这个测试就能访问该类的私有成员。本文基于 GoogleTest 仓库文档和测试代码给出从声明到编译运行的完整操作路径。适用前提支持 C17 的 C 编译器、CMake 与 GoogleTest下文用 CMake 的FetchContent方式引入。理解 FRIEND_TEST 宏的实际作用宏的定义在 gtest_prod.h 中#define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test它把参数拼接成 GoogleTest 内部为测试生成的类名并声明为friend class。因此宏必须写在被测类的类体内部通常在private:区域它针对的是某一个具体测试TestSuiteNameTestName的组合而不是整个测试类所以每要放行一个测试就要多写一条FRIEND_TEST使用 fixture 的TEST_F同样适用因为 GoogleTest 会为TEST_F生成对应的测试类友元声明对生成的类生效。注意这个头文件是为生产代码准备的被测类的头文件里#include gtest/gtest_prod.h即可测试文件本身包含gtest/gtest.h。在被测类中声明友元测试仓库自带的测试 production.h 展示了一个完整的被测试类覆盖了不带 fixture 和带 fixture 两种写法#include gtest/gtest_prod.h class PrivateCode { public: // Declares a friend test that does not use a fixture. FRIEND_TEST(PrivateCodeTest, CanAccessPrivateMembers); // Declares a friend test that uses a fixture. FRIEND_TEST(PrivateCodeFixtureTest, CanAccessPrivateMembers); PrivateCode(); int x() const { return x_; } private: void set_x(int an_x) { x_ an_x; } int x_; };两条宏分别放行一个普通TEST和一个TEST_F被放行的测试都能访问私有的set_x()和成员变量x_。编写访问私有成员的测试对应上面的类gtest_prod_test.cc 展示了两种测试的写法#include production.h #include gtest/gtest.h // Tests that private members can be accessed from a TEST declared as // a friend of the class. TEST(PrivateCodeTest, CanAccessPrivateMembers) { PrivateCode a; EXPECT_EQ(0, a.x_); a.set_x(1); EXPECT_EQ(1, a.x_); } typedef testing::Test PrivateCodeFixtureTest; // Tests that private members can be accessed from a TEST_F declared // as a friend of the class. TEST_F(PrivateCodeFixtureTest, CanAccessPrivateMembers) { PrivateCode a; EXPECT_EQ(0, a.x_); a.set_x(2); EXPECT_EQ(2, a.x_); }两个要点FRIEND_TEST(TestSuiteName, TestName)中的两个参数必须和TEST/TEST_F的宏参数一一对应拼错任何一处友元声明就会失配编译时报private访问错误。TEST_F需要一个 fixture 类型。仓库示例直接用typedef testing::Test PrivateCodeFixtureTest;满足这一点如果你有自己的 fixture 类把它定义成和测试同名的类即可。命名空间限制测试必须与被测类同命名空间这是文档中特别强调的约束。如果被测类定义在某个命名空间内要让测试成为友元fixture 和测试必须定义在完全相同的命名空间里不能是匿名命名空间或 inline 命名空间gtest_prod.h 的注释和 reference/testing.md 的FRIEND_TEST条目都指出了这一点。文档给出的示例namespace my_namespace { class MyClass { friend class MyClassTest; FRIEND_TEST(MyClassTest, HasPropertyA); FRIEND_TEST(MyClassTest, HasPropertyB); ... definition of class MyClass ... }; } // namespace my_namespace对应的测试代码必须写成namespace my_namespace { class MyClassTest : public testing::Test { ... }; TEST_F(MyClassTest, HasPropertyA) { ... } TEST_F(MyClassTest, HasPropertyB) { ... } } // namespace my_namespace如果你的生产类在默认命名空间像上面的PrivateCode则测试直接写在文件作用域即可不需要额外包一层 namespace。用 CMake 构建并运行验证按 docs/quickstart-cmake.md 的方式组织工程。项目目录下的CMakeLists.txtcmake_minimum_required(VERSION 3.14) project(my_project) # GoogleTest requires at least C17 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) # For Windows: Prevent overriding the parent projects compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL FORCE) FetchContent_MakeAvailable(googletest) enable_testing() add_executable( production_test production.h gtest_prod_test.cc ) target_link_libraries( production_test GTest::gtest_main ) include(GoogleTest) gtest_discover_tests(production_test)其中FetchContent_Declare的 URL 是 quickstart 文档原样给出的地址commit hash03597a01ee50ed33e9dfd640b249b4be3799d395对应文档推荐的 GoogleTest 版本Windows 平台的gtest_force_shared_crt设置仅在 Windows 上需要。测试源文件按上一步的代码放入项目目录。然后在项目目录执行cmake -S . -B build cmake --build build cd build ctest运行成功时文档展示的 ctest 输出形如文档示例实际路径和耗时会有差异Test project .../my_project/build Start 1: PrivateCodeTest.CanAccessPrivateMembers 1/2 Test #1: PrivateCodeTest.CanAccessPrivateMembers ... Passed 2/2 Test #2: PrivateCodeFixtureTest.CanAccessPrivateMembers ... Passed 100% tests passed, 0 tests failed out of 2判断方式两条测试都Passed说明友元声明生效、私有成员访问被编译器放行且断言成立如果编译阶段就报私有成员访问错误检查FRIEND_TEST的两个参数是否与TEST/TEST_F完全一致、以及命名空间是否对齐。限制与替代路径docs/advanced.md 的 Testing Private Code 一节先给出了立场按黑盒测试原则大多数时候应通过公共接口测试如果频繁需要测试内部实现文档建议先考虑把实现拆到独立的实现类中再测试。因此FRIEND_TEST适合确实必须的场景文档同时给出两条替代路径fixture 友元 accessor把测试 fixture 声明为被测类的友元在 fixture 里定义访问器TEST_F通过访问器读取私有成员。注意 fixture 是友元并不自动让子测试类成为友元这正是FRIEND_TEST存在的意义。*-internal.h实现类把私有逻辑重构进实现类声明放在*-internal.h生产代码和测试可以包含该头文件外部客户端不可以。参考位置宏定义gtest_prod.h完整示例生产类 测试production.h、gtest_prod_test.cc私有代码测试原则与替代方案docs/advanced.md宏参考条目docs/reference/testing.mdCMake 构建流程docs/quickstart-cmake.md【免费下载链接】googletestGoogleTest - Google Testing and Mocking Framework项目地址: https://gitcode.com/GitHub_Trending/go/googletest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表