如何在 gtest 中使用带有命名空间的朋友 class

How to use friend class with namespace in gtest

假设我的 Add.h 在一个命名空间内,我将它设为 AddTest 的友元,以便它可以访问 AddTwoNumber。

namespace mynamespace
{

class Add
{
 friend class AddTest;

 public:
  Add(){};
  ~Add(){};

 private:
  int AddTwoNumber(const int a, const int b){return a+b};
};

}

我的AddTest.h是

#include "Add.h"
#include "gtest/gtest.h"

class AddTest : public ::testing::Test
{
 protected:
  AddTest(){};
  virtual ~AddTest(){};

  virtual void SetUp()
  {
    mynamespace::Add addobj;
    result = addobj.AddTwoNumber(2, 3);
  };

  virtual void TearDown(){};

  int result;
};

但是,它返回错误,AddTwoNumber 是私有的。如果我在 Add.h 中取出 "mynamespace",代码就可以工作。有没有办法保留命名空间,但仍允许 AddTest 访问 Add.h 中的私有方法?

使用

将 AddTest 限定在全局命名空间中
friend class ::AddTest;

没有 :: 它将声明 nynamespace::AddTest 为朋友。

测试代码不应出现在生产代码的声明中。换句话说,如果 AddTwoNumber 需要测试,它的行为应该可以通过 class Add 的 public 成员进行测试和观察。如果没有人能从Add的class的可调用接口观察到AddTwoNumber的后果,那它怎么能做任何有用的事情呢?

当您编写测试先行的代码时,您最终会自然而然地获得遵循此组织的生产代码。当您之后编写测试时,您最终会遇到您所描述的要测试的东西被埋在里面的情况。这是遗留代码(未经测试的代码)的情况。在编写测试之前编写实现时,您正在创建遗留代码。

有关使用遗留代码的更多详细信息,请参阅 Michael Feathers 的书 "Working Effectively with Legacy Code"。他描述了许多解耦代码的技术,这样您就可以测试它而不会不必要地污染您的 public 声明。

立即查看我的 C++! 2014 年 Test-Driven Development in C++ 研讨会,简要介绍了使用 Boost.Test 在 C++ 中进行测试驱动开发。研讨会包括演示文稿中每个步骤的代码,因此您可以直接在计算机上按照演示文稿进行操作。

Jeff Langr 的书 "Modern C++ Programming with Test-Driven Development" 是对使用现代 C++ 进行测试驱动开发的出色论述。 Jeff 的书有一个参考书目,引用了显示测试驱动开发的好处的实证研究。