如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?

仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。


当前回答

在C#中,您可以使用System.Reflection,尽管在Java中我不知道。如果你“觉得你需要对私有方法进行单元测试”,我的猜测是还有其他一些地方是错误的。。。

我会认真考虑用新的眼光重新审视我的建筑。。。

其他回答

测试私有方法的最佳方法是通过另一个公共方法。如果无法做到这一点,则以下条件之一为真:

私有方法是死代码您正在测试的类附近有设计气味您尝试测试的方法不应是私有的

对于C++(从C++11开始),将测试类添加为好友非常有效,不会破坏生产封装。

让我们假设我们有一些类Foo和一些真正需要测试的私有函数,还有一些类FooTest应该可以访问Foo的私有成员。然后我们应该写下以下内容:

// prod.h: some production code header

// forward declaration is enough
// we should not include testing headers into production code
class FooTest;

class Foo
{
  // that does not affect Foo's functionality
  // but now we have access to Foo's members from FooTest
  friend FooTest;
public:
  Foo();
private:
  bool veryComplicatedPrivateFuncThatReallyRequiresTesting();
}
// test.cpp: some test
#include <prod.h>

class FooTest
{
public:
  void complicatedFisture() {
    Foo foo;
    ASSERT_TRUE(foo.veryComplicatedPrivateFuncThatReallyRequiresTesting());
  }
}

int main(int /*argc*/, char* argv[])
{
  FooTest test;
  test.complicatedFixture();  // and it really works!
}

从测试框架测试Java私有方法的最佳合法方法是在方法上添加@VisibleForTesting注释,因此相同的方法将像公共方法一样在测试框架中可见。

我认为大多数答案都太粗糙了。这取决于您的代码是否应该测试私有方法。

我过去使用了私人方法测试,我是通过反思来完成的。它对我有用。我意识到它的问题,但对我来说,这是最好的解决方案。

我有一个强大的应用程序,可以模拟100多万人口中的人类行为。每个人都由一个对象表示。该应用程序的主要目的是跟踪某些东西(疾病、信息、思想)如何在人群中传播。

为此,我有方法将疾病或信息从一个对象传递给另一个对象。绝对没有理由公开这些方法,因为最终用户对人与人之间的一次传递不感兴趣。最终用户只对它如何在人群中传播的全貌感兴趣。所以这些方法是私人的。

但我想肯定的是,从一个人向另一个人传递一点信息的行为是否在做它应该做的事情。通过公共用户界面测试它也是不可能的,因为它只是不公开,我认为仅仅为了测试而公开它是很尴尬的。应用程序的最终输出由一直执行的数亿个这样的单个步骤定义。我也不能测试最终输出,因为这涉及到复杂的随机性,这使得它无法预测。

因此,我测试应用程序的方法是测试从一个人向另一个人传递信息的单个步骤。这些都是私人方法。所以我用反思来检验这一点。

我讲这个故事是为了表明这不是一个简单的黑白故事。这取决于您的应用程序。在某些情况下,通过反射测试私有方法可能是最好的选择。

如果这里的一些人在我的用例中知道更好的解决方案,我当然乐意接受纠正。。。。

我和我的团队正在使用Typemock,它有一个API,允许您伪造非公共方法。

最近,他们增加了伪造不可见类型和使用xUnit的能力。