【问题标题】:Accessing protected variable in googletest在 googletest 中访问受保护的变量
【发布时间】:2014-12-06 02:11:38
【问题描述】:

我有这个类 testC 用于谷歌测试

class testC : public A { };

然后是同一个文件中的一堆 TEST。

TEST(test_case_name, test_name) {
 ... test body ...
}

A 的结构是这样的

class A{

protected:
   B b;
public:
   //constructors
   //destructor
   //member functions

问:如何通过testC访问所有TEST(){}函数中的b

我尝试在 testC 中做一个吸气剂

public:
  testC getTest(){
      testC test;
      return test;
  }

我也尝试返回参考,但没有运气......

【问题讨论】:

  • 为什么要从测试中派生测试类?
  • 按照说明...有更优化的方法吗?
  • @anhoppe 在下面给出了如何做到这一点的正确答案,但通常当你遇到这个问题时,你必须问为什么你需要它。单元测试应该测试系统的预期行为。如果您需要检查私有成员的行为,那么您正在检查子系统的状态。如果那个子系统需要这样的测试,它通常应该是它自己的类,有它自己的一组单元测试。

标签: c++ googletest protected


【解决方案1】:

试试 googletest 提供的 FRIEND_TEST 宏。查看Private class members 下的高级指南。

您必须将测试声明为被测代码的朋友。如果我没记错的话,你必须为所有想要访问受保护成员的测试声明友谊。

class MySystemUnderTest
{
    #ifdef _MY_UNIT_TEST
    FRIEND_TEST(MySystemUnderTest_test, functionA_prereq_expected);
    FRIEND_TEST(MySystemUnderTest_test, functionB_prereq_expected);
    #endif

    ...
};

在上面的示例中,我使用预处理器符号 _MY_UNIT_TEST 从生产代码中删除声明。 functionA_prereq_expectedfunctionB_prereq_expected 方法将在测试夹具 MySystemUnderTest_test 中定义。

您必须在被测代码中添加 FRIEND_TEST 声明。如果您想针对受保护/私有成员进行测试,这就是您必须付出的代价。

【讨论】:

  • 我是否需要在 testC 中创建一个对象,例如 private: testC testO;
  • 如果我的代码正确,则 TEST(testCaseName, testName) 定义不属于 testC 类。它们不是它的成员,并且无法访问受保护的成员,无论您是否返回对 testC 对象的引用或其他任何内容。您的测试访问它们的唯一方法是将 FRIEND_TEST(testCaseName, testName) 声明添加到 testC 类。然后测试是一个朋友并且可以访问受保护的和私有的成员。但确实如上所述,这通常不是一种好的风格。
  • 查看链接。它真的应该解释这个话题。高级指南真的很棒!通过一些尝试,你会成功的:-)
  • Updated link here这里用粗体显示文本很重要“根据黑盒测试原则,大多数时候你应该通过它的公共接口来测试你的代码。”
【解决方案2】:

我不会将FRIEND_TEST 直接添加到要测试的类中ClassToTest#ifdef 语句包围(如post by anhoppe 所建议的)protected 成员和方法我会创建另一个test::ClassToTest 类继承自要测试的类,并将测试套件和测试注册为好友,如下所示:

内部文件implementation.hpp:

namespace some {
  namespace complicated {
    namespace ns {
      // Class that we want to test
      class ClassToTest {
        public:
          constexpr ClassToTest() noexcept
            : member_to_be_accessed{7} {
            return;
          }
        protected:
          // The protected member (or method) to be accessed
          int member_to_be_accessed;
      };
    }
  }
}

文件内test.hpp

#include <gtest/gtest.h>

#include "implementation.hpp"


namespace test {
  // The derived class that registers the test fixture and tests as friends
  class ClassToTest : public some::complicated::ns::ClassToTest {
    using some::complicated::ns::ClassToTest::ClassToTest;
    friend class SomeTestFixture;
    FRIEND_TEST(SomeTestFixture, someTest);
  };
  // The test fixture
  class SomeTestFixture : public testing::Test {
    protected:
      SomeTestFixture() noexcept 
        : class_to_test{} {
        return;
      }
      ClassToTest class_to_test;
  };
  // A test
  TEST_F(SomeTestFixture, someTest) {
    EXPECT_EQ(class_to_test.member_to_be_accessed, 7);
  }
}

这样做的好处是您清楚地将测试与实现分开,并且您可以绕过restriction regarding namespaces

如果类被定义在一个命名空间中,那么为了成为它的朋友 类、测试装置和测试必须以完全相同的方式定义 命名空间,没有内联或匿名命名空间。


此外,正如"Testing Private Code" section of the "Advanced GoogleTest Guide" 中所指出的,通常应使用黑盒方法:代码应仅通过其公共接口进行测试。如果可以,请使用Pointer to Implementation (PImpl) 设计策略重新构建将接口与实现分开的代码,并独立测试内部结构。

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2014-05-14
    • 2019-10-27
    • 2013-04-09
    • 1970-01-01
    • 2016-02-19
    • 2011-03-29
    • 2023-01-13
    相关资源
    最近更新 更多