为了提升代码质量,减少缺陷,方便以后修改代码,除了对类中public方法编写单元测试案例以外,最好对私有方法也编写测试案例。方法也简单,利用java的反射,获得私有方法的Method对象,然后直接调用即可。
获得私有方法的Method对象的方法如下:
/**
* 测试私有方法时使用,将类的私有方法转换成可访问的方法。
* @param clazz 类的类型,不能为空
* @param methodName 方法名称,不能为空
* @param argClasses 方法的参数类数组,不能为空,也不能没有元素
* @return 可访问的方法对象
*/
public static Method getPrivateMethodForTest(Class<?> clazz,
String methodName, Class<?>[] argClasses)
throws NoSuchMethodException, SecurityException {
if (clazz == null || methodName == null || argClasses== null) {
throw new IllegalArgumentException("clazz、methodName和argClasses都不能为空。");
}
// 获取私有方法和他的参数
Method method = clazz.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true); // 允许访问
return method;
}
如果要获取类的私有属性值,可以使用此方法:
/**
* 获取私有类属性的值
*
* @param clazz
* 类的类型,不能为空
* @param obj
* 类的实例,不能为空
* @param fieldName
* 类属性名称,不能为空
* @return 类属性的值
* @throws NoSuchFieldException
* 类属性名称不存在时抛出
* @throws SecurityException
* @throws IllegalArgumentException
* 三个参数中任一参数为空时抛出
* @throws IllegalAccessException
*/
public static Object getPrivateFieldValue(Class<?> clazz, Object obj,
String fieldName) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
if (clazz == null || obj == null || fieldName == null) {
throw new IllegalArgumentException("clazz、obj和fieldName都不能为空");
}
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
}
如果要设置类私有属性的值,可以使用此方法:
/**
* 设置私有类属性的值
*
* @param clazz
* 类的类型,不能为空
* @param obj
* 类的实例,不能为空
* @param fieldName
* 类属性名称,不能为空
* @param value
* 类属性的值
* @throws NoSuchFieldException
* 类属性名称不存在时抛出
* @throws SecurityException
* @throws IllegalArgumentException
* 三个参数中任一参数为空时抛出
* @throws IllegalAccessException
*/
public static void setPrivateFieldValue(Class<?> clazz, Object obj,
String fieldName, Object value) throws NoSuchFieldException,
SecurityException, IllegalArgumentException, IllegalAccessException {
if (clazz == null || obj == null || fieldName == null) {
throw new IllegalArgumentException("clazz、obj和fieldName都不能为空");
}
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
得到私有方法的Method对象以后,可以这么调用:
public void testGetPrivateMethodForTest() throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Method method = TestCaseHelper.getPrivateMethodForTest(obj.getClass(),
"sayHello", new Class[] { String.class });
String returnValue = (String) method
.invoke(obj, new Object[] { "Sam" });
Assert.assertEquals("Hello, Sam", returnValue);
}