
翻译自 https://medium.com/mindorks/how-to-unit-test-private-methods-in-java-and-kotlin-d3cae49dccd
❓如何单元测试 Kotlin/Java 中的 private 方法❓
首先,开发者应该测试代码里的 private 私有方法吗?
直接信任这些私有方法,测试到调用它们的公开方法感觉就够了吧。
对于这个争论,每个开发者都会有自己的观点。
但回到开头的问题本身,到底有没有一种合适的途径来实现私有方法的单元测试?
截止到目前,在面对单元测试私有方法的问题时,一般有如下几种选择:
-
不去测试私有方法 😜*(选择信任,直接躺平)*
-
将目标方法临时改成 public 公开访问权限 😒(可我不愿意这样做,这不符合代码规范。作为一名开发者,我要遵循最佳实践)
-
使用嵌套的测试类 😒*(将测试代码和生产代码混到一起不太好吧,我再强调一遍:我是很优秀的开发者,要遵循最佳实践)*
-
使用 Java 反射机制 😃*(听起来还行,可以试试这个方案)*
大家都知道通过 Java 反射机制可以访问到其他类中的私有属性和方法,而且写起来也不麻烦,在单元测试里采用该机制应该也很容易上手。
注意:
只有将代码作为独立的 Java 程序运行时,这个方案才适用,就像单元测试、常规的 Java 应用程序。但如果在 Java Applet 上执行反射,则需要对 SecurityManager 做些干预。由于这不是高频场景,本文不对其作额外阐述。
Java 8 中添加了对反射方法参数的支持,使得开发者可以在运行时获得参数名称。
访问私有属性
Class 类提供的 getField(String name) 和 getFields() 只能返回公开访问权限的属性,访问私有权限的属性则需要调用 getDeclaredField(String name) 或 getDeclaredFields()。
下面是一个简单的代码示例:一个拥有私有属性的类以及如何通过 Java 反射来访问这个属性。
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
上述代码将打印出如下结果:内容来自于 PrivateObject 实例的私有属性 privateString 的值。
fieldValue = The Private Value
需要留意的是,getDeclaredField("privateString") 能返回私有属性没错,但其范围仅限 class 本身,不包含其父类中定义的属性。
还有一点是需要调用 Field.setAcessible(true),目的在于关闭反射里该 Field 的访问检查。
这样的话,如果访问的属性是私有的、受保护的或者包可见的,即使调用者不满足访问条件,仍然可以在反射里获取到该属性。当然,非反射的正常代码里依然无法获取到该属性,不受影响。
访问私有方法
和访问私有属性一样,访问私有方法需要调用 Class 类提供的 getDeclaredMethod(String name, Class[] parameterTypes) 或 Class.getDeclaredMethods()。
同样的,我们展示一段代码示例:定义了私有方法的类以及通过反射访问它。
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
private String getPrivateString(){
return this.privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null)

本文探讨了Java和Kotlin中私有方法的单元测试问题。对于是否测试私有方法开发者观点不一,文中介绍了几种单元测试私有方法的选择,重点阐述了使用Java反射机制访问私有属性和方法,并给出代码示例,最后展示了如何用反射进行单元测试,帮助开发者覆盖私有方法。
最低0.47元/天 解锁文章
1274

被折叠的 条评论
为什么被折叠?



