如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
当前回答
如果您只使用Mockito:
您可以将私有方法视为正在测试的公共方法的一部分。您可以确保在测试公共方法时覆盖私有方法中的所有情况。
假设您是一个仅限Mockito的用户(不允许或不想使用PowerMock或反射或任何此类工具),并且不想更改正在测试的现有代码或库,这可能是最好的方法。
如果选择这种方式,唯一需要处理的就是在私有方法中本地声明的变量(用户定义的对象)。如果私有方法依赖于本地声明的变量对象及其方法,请确保将这些用户定义的对象全局声明为私有对象,而不是本地声明的对象。您可以在本地实例化这些对象。
这允许您模拟这些对象并将它们注入回测试对象。你也可以模仿(使用when/then)他们的方法。
这将允许您在测试公共方法时无错误地测试私有方法。
优势
代码覆盖范围能够测试完整的私有方法。
缺点
对象的作用域如果您不希望对象公开给同一类中的其他方法,这可能不是您的方式。当在不同的公共方法和/或在同一方法中多次调用时,您可能会多次测试私有方法。
其他回答
如果你担心没有像很多帖子所建议的那样测试私有方法,那么考虑一下代码覆盖工具将准确地确定你的代码被测试了多少以及泄漏的地方,所以这样做是可以接受的。
将问题作者引向“变通方法”的答案对社区造成了巨大的伤害。测试是所有工程学科的主要组成部分。你不会想买一辆没有经过适当测试的汽车,而且测试的方式很有意义,那么为什么有人会想购买或使用测试不好的软件呢?人们这样做的原因可能是因为测试不好的软件的影响是事后才感受到的,我们通常不会把它们与身体伤害联系起来。
这是一种非常危险的观念,很难改变,但我们有责任提供安全的产品,而不管管理层如何欺负我们。想想Equifax黑客。。。
我们必须努力营造一个鼓励良好软件工程实践的环境。这并不意味着排斥我们中那些不认真对待自己手艺的弱者/懒惰者,而是创造一种责任感和自我反思的现状,鼓励每个人在精神和技能上追求成长。
我仍在学习,可能自己也有错误的看法/观点,但我坚信,我们需要对良好做法负责,避免不负责任的黑客或解决问题的方法。
从本文:使用JUnit和SuiteRunner测试私有方法(Bill Venners)中,您基本上有4个选项:
不要测试私有方法。授予方法包访问权限。使用嵌套测试类。使用反射。
如果您的测试类与应该测试的类在同一个包中呢?
当然,在另一个目录中,源代码使用src&classes,测试类使用test/src和test/classes。让类和测试/类位于类路径中。
我不确定这是否是一种好的技术,但我开发了以下模式来单元测试私有方法:
我不修改要测试的方法的可见性,也不添加其他方法。相反,我为要测试的每个私有方法添加了一个额外的公共方法。我调用这个额外的方法TestPort,并用前缀t_表示它们。然后,此测试端口方法只需访问相应的私有方法。
此外,我向测试端口方法添加了一个布尔标志,以决定是否从外部通过测试端口方法授予对私有方法的访问权。然后在静态类中全局设置该标志,在该类中我放置了例如应用程序的其他全局设置。因此,我可以在一个地方打开和关闭对私有方法的访问,例如,在相应的单元测试中。
Android具有Android.support.annotation包中的@VisibleForTesting注释。
@VisibleForTesting注释表明,一个带注释的方法比通常情况下使方法可测试所需的方法更可见。此注释有一个可选的otherwise参数,如果不需要使方法在测试中可见,则可以指定该方法的可见性。Lint使用otherwise参数来强制实现预期的可见性。
实际上,这意味着您应该打开一个方法进行测试,@VisibleForTesting注释将显示警告。
例如
package com.mypackage;
public class ClassA {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static void myMethod() {
}
}
当您在同一个包(com.mypackage)中调用ClassA.myMethod()时,您将看到警告。