如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
当前回答
Groovy有一个bug/特性,通过它可以调用私有方法,就像它们是公共的一样。因此,如果您能够在项目中使用Groovy,那么可以使用它来代替反射。查看此页面以获取示例。
其他回答
正如上面许多人所建议的,一个好的方法是通过公共接口测试它们。
如果您这样做,最好使用代码覆盖工具(如EMMA)来查看您的私有方法是否确实在测试中执行。
这是我的龙目样本:
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Student student = new Student();
Field privateFieldName = Student.class.getDeclaredField("name");
privateFieldName.setAccessible(true);
privateFieldName.set(student, "Naruto");
Field privateFieldAge = Student.class.getDeclaredField("age");
privateFieldAge.setAccessible(true);
privateFieldAge.set(student, "28");
System.out.println(student.toString());
Method privateMethodGetInfo = Student.class.getDeclaredMethod("getInfo", String.class, String.class);
privateMethodGetInfo.setAccessible(true);
System.out.println(privateMethodGetInfo.invoke(student, "Sasuke", "29"));
}
@Setter
@Getter
@ToString
class Student {
private String name;
private String age;
private String getInfo(String name, String age) {
return name + "-" + age;
}
}
从本文:使用JUnit和SuiteRunner测试私有方法(Bill Venners)中,您基本上有4个选项:
不要测试私有方法。授予方法包访问权限。使用嵌套测试类。使用反射。
您可以关闭反射的Java访问限制,这样私有就没有什么意义了。
setAccessible(true)调用实现了这一点。
唯一的限制是ClassLoader可能不允许您这样做。
有关在Java中实现这一点的方法,请参阅颠覆单元测试的Java访问保护(Ross Burton)。
我使用的另一种方法是将私有方法更改为打包私有或受保护的方法,然后使用GoogleGuava库的@VisibleForTesting注释对其进行补充。
这将告诉使用此方法的任何人要小心,即使在包中也不要直接访问它。同样,测试类不需要在物理上位于同一个包中,而是位于测试文件夹下的同一包中。
例如,如果要测试的方法位于src/main/java/mybackage/MyClass.java中,那么您的测试调用应该位于src/test/java/mypackage/MiClassTest.java中。这样,您就可以访问测试类中的测试方法。