我知道如何从Test class
内的Class
访问private
method
或field
:
访问MyClass
的私有方法,命名为void doSomething()
:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
...
try {
Method method = MyClass.class.getDeclaredMethod("doSomething", (Class[])null); // (Class[])null is for parameterless methods
method.setAccessible(true);
method.invoke(localInstanceOfMyClass);
}
catch (NoSuchMethodException ex){
ex.printStackTrace();
}
catch (IllegalAccessException ex){
ex.printStackTrace();
}
catch (IllegalArgumentException ex){
ex.printStackTrace();
}
catch (InvocationTargetException ex) {
ex.printStackTrace();
}
访问MyClass
的私有字段,命名为boolean myField
:
import java.lang.reflect.Field;
...
try {
Field field = MyClass.class.getDeclaredField("myField");
field.setAccessible(true);
field.set(localInstanceOfMyClass, true); // true is the value I want to assign to myField
}
catch (NoSuchFieldException ex){
ex.printStackTrace();
}
catch (IllegalAccessException ex){
ex.printStackTrace();
}
catch (IllegalArgumentException ex){
ex.printStackTrace();
}
(来源:https://stackoverflow.com/a/34658/1682559)
你可以看到,这是相当多的代码,只是把private boolean
放在true
或false
。
所以,我的问题:是否有可能以某种方式使两个public static methods
,两个用于Method
,一个用于Field
,我可以在所有Test Classes
中使用?澄清:
TestMethodsClass.setPrivateField(... some parameters ...);
TestMethodsClass.runPrivateVoidMethod(... some parameters ...);
TestMethodsClass.runPrivateReturnMethod(... some parameters ...);
根据上面void doSomething()
en boolean myField
示例的参数举例:
TestMethodsClass.setPrivateField(localInstanceOfMyClass, "myField", true);
TestMethodsClass.runPrivateVoidMethod(localInstanceOfMyClass, "doSomething", null);
// PS: null will be converted in the method itself to (Class[])null`
提前感谢您的回复。
好吧,这其实很简单。
TestMethodsClass:
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMethodsClass
{
public static void runPrivateVoidMethod(Object ob, String methodName, Class<?>[] parameters){
try {
Method method = null;
if(parameters == null){
Class<?>[] nullParameter = (Class[])null;
method = ob.getClass().getDeclaredMethod(methodName, nullParameter);
}
else
method = ob.getClass().getDeclaredMethod(methodName, parameters);
if(method != null){
method.setAccessible(true);
method.invoke(ob);
}
}
catch (NoSuchMethodException ex){
ex.printStackTrace();
}
catch (IllegalAccessException ex){
ex.printStackTrace();
}
catch (IllegalArgumentException ex){
ex.printStackTrace();
}
catch (InvocationTargetException ex) {
ex.printStackTrace();
}
}
public static Object runPrivateReturnMethod(Object ob, String methodName, Class<?>[] parameters){
Object returnObject = null;
try {
if(parameters == null){
Class<?>[] nullParameter = (Class[])null;
Method method = ob.getClass().getDeclaredMethod(methodName, nullParameter);
method.setAccessible(true);
returnObject = method.invoke(ob);
}
else{
Method method = ob.getClass().getDeclaredMethod(methodName, parameters);
method.setAccessible(true);
method.invoke(ob);
}
}
catch (NoSuchMethodException ex){
ex.printStackTrace();
}
catch (IllegalAccessException ex){
ex.printStackTrace();
}
catch (IllegalArgumentException ex){
ex.printStackTrace();
}
catch (InvocationTargetException ex) {
ex.printStackTrace();
}
return returnObject;
}
public static void setPrivateField(Object ob, String fieldName, Object value){
try {
Field field = ob.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(ob, value);
}
catch (NoSuchFieldException ex){
ex.printStackTrace();
}
catch (IllegalAccessException ex){
ex.printStackTrace();
}
catch (IllegalArgumentException ex){
ex.printStackTrace();
}
}
}
如何命名:
// Set private field "boolean myField" from MyClass to true
TestMethodsClass.setPrivateField(localInstanceOfMyClass, "myField", true);
// Run private method "doSomething()" from MyClass
TestMethodsClass.runPrivateVoidMethod(localInstanceOfMyClass, "doSomething", null);
// Run private method "doSomething()" from MyClass and assign the return value to a local field
boolean test = (boolean)TestMethodsClass.runPrivateReturnMethod(localInstanceOfMyClass, "doSomething", null);
我还没有完全测试过,所以我不知道它是否适用于所有类型。但据我所知,字符串和布尔值工作得很好。我会做更多的测试,当我有一些空闲时间从我的项目。