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

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


当前回答

一般来说,单元测试旨在使用类或单元的公共接口。因此,私有方法是您不希望显式测试的实现细节。

其他回答

从本文:使用JUnit和SuiteRunner测试私有方法(Bill Venners)中,您基本上有4个选项:

不要测试私有方法。授予方法包访问权限。使用嵌套测试类。使用反射。

我倾向于不测试私人方法。这里有疯狂。我个人认为,你应该只测试你公开的接口(包括受保护的和内部的方法)。

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

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

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

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

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

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

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

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

PowerMockito就是为此而生的。

使用Maven依赖项:

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-core</artifactId>
        <version>2.0.7</version>
        <scope>test</scope>
    </dependency>

那你就可以了

import org.powermock.reflect.Whitebox;
...
MyClass sut = new MyClass();
SomeType rval = Whitebox.invokeMethod(sut, "myPrivateMethod", params, moreParams);

私有方法被公共方法使用。否则,它们就是死代码。这就是为什么要测试公共方法,断言公共方法的预期结果,从而断言它使用的私有方法。

在公共方法上运行单元测试之前,应该通过调试来测试私有方法。

也可以使用测试驱动开发来调试它们,调试单元测试,直到满足所有断言。

我个人认为最好使用TDD创建类;创建公共方法存根,然后使用预先定义的所有断言生成单元测试,这样在编写代码之前就可以确定方法的预期结果。这样,就不会走上使单元测试断言符合结果的错误道路。然后,当所有单元测试通过时,您的类是健壮的并满足要求。