如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
当前回答
下面的ReflectionTestUtil可以通用地用于测试私有方法的原子性。
import com.google.common.base.Preconditions;
import org.springframework.test.util.ReflectionTestUtils;
/**
* <p>
* Invoker
* </p>
*
* @author
* @created Oct-10-2019
*/
public class Invoker {
private Object target;
private String methodName;
private Object[] arguments;
public <T> T invoke() {
try {
Preconditions.checkNotNull(target, "Target cannot be empty");
Preconditions.checkNotNull(methodName, "MethodName cannot be empty");
if (null == arguments) {
return ReflectionTestUtils.invokeMethod(target, methodName);
} else {
return ReflectionTestUtils.invokeMethod(target, methodName, arguments);
}
} catch (Exception e) {
throw e;
}
}
public Invoker withTarget(Object target) {
this.target = target;
return this;
}
public Invoker withMethod(String methodName) {
this.methodName = methodName;
return this;
}
public Invoker withArguments(Object... args) {
this.arguments = args;
return this;
}
}
Object privateMethodResponse = new Invoker()
.withTarget(targetObject)
.withMethod(PRIVATE_METHOD_NAME_TO_INVOKE)
.withArguments(arg1, arg2, arg3)
.invoke();
Assert.assertNotNutll(privateMethodResponse)
其他回答
如果您的测试类与应该测试的类在同一个包中呢?
当然,在另一个目录中,源代码使用src&classes,测试类使用test/src和test/classes。让类和测试/类位于类路径中。
在过去,我曾为Java使用过反射,在我看来这是一个很大的错误。
严格来说,您不应该编写直接测试私有方法的单元测试。您应该测试的是类与其他对象的公共契约;您不应该直接测试对象的内部。如果另一个开发人员想要对类进行一个小的内部更改,这不会影响类的公共契约,那么他/她就必须修改基于反射的测试,以确保它正常工作。如果在整个项目中重复这样做,那么单元测试就不再是代码健康状况的有用度量,而开始成为开发的障碍,成为开发团队的烦恼。
相反,我建议使用一个代码覆盖工具,例如Cobertura,以确保您编写的单元测试在私有方法中提供代码的适当覆盖。通过这种方式,您可以间接测试私有方法正在做什么,并保持更高级别的灵活性。
我不确定这是否是一种好的技术,但我开发了以下模式来单元测试私有方法:
我不修改要测试的方法的可见性,也不添加其他方法。相反,我为要测试的每个私有方法添加了一个额外的公共方法。我调用这个额外的方法TestPort,并用前缀t_表示它们。然后,此测试端口方法只需访问相应的私有方法。
此外,我向测试端口方法添加了一个布尔标志,以决定是否从外部通过测试端口方法授予对私有方法的访问权。然后在静态类中全局设置该标志,在该类中我放置了例如应用程序的其他全局设置。因此,我可以在一个地方打开和关闭对私有方法的访问,例如,在相应的单元测试中。
正如其他人所说。。。不要直接测试私有方法。以下是一些想法:
保持所有方法的规模和重点(易于测试,易于发现错误)使用代码覆盖工具。我喜欢Cobertura(哦,快乐的一天,它看起来像是一个新版本!)
在单元测试上运行代码覆盖率。如果您发现方法没有经过充分测试,请添加到测试中以提高覆盖率。目标是100%的代码覆盖率,但要意识到你可能无法做到这一点。
如果您确实需要直接测试私有方法/类等,那么可以使用其他答案中已经提到的反射。然而,如果说到这一点,我宁愿使用框架提供的实用程序类,而不是直接处理反射。例如,对于Java,我们有:
Spring框架中的ReflectionUtilsJUnit中的ReflectionUtils
关于如何使用它们,你可以在网上找到很多文章。我特别喜欢这个:
org.springframework.util.ReflectionUtils的Java代码示例