Parfois, je fais une seule unité avec JUnit, mais il est difficile de créer un processus pour exécuter une méthode privée à chaque fois, alors notez ici. Ce n'est pas limité aux tests, mais il est probablement utilisé uniquement pour le code de test.
Params.java
package com.example.demo.util;
import java.lang.reflect.Method;
public class ReflectionUtil {
/**
*Exécuter une méthode privée (sans argument).
* @Instance qui exécute la méthode param obj
* @param methodName nom de la méthode
* @argument param params
* @valeur de retour de la méthode de retour
* @throws Exception
*/
public static Object invokePrivate(Object obj, String methodName) throws Exception {
Class<?> clazz = obj.getClass();
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
return method.invoke(obj);
}
/**
*Exécuter une méthode privée (avec des arguments).
* @Instance qui exécute la méthode param obj
* @param methodName nom de la méthode
* @argument param params
* @valeur de retour de la méthode de retour
* @throws Exception
*/
public static Object invokePrivate(Object obj, String methodName, Params params) throws Exception {
if(params == null ){
throw new NullPointerException("params is required");
}
Class<?> clazz = obj.getClass();
Method method = clazz.getDeclaredMethod(methodName, params.getTypes());
method.setAccessible(true);
return method.invoke(obj, params.getArgs());
}
}
Au fait, getDeclaredMethod récupère l'objet méthode de l'objet java.lang.Class, vous n'avez donc pas besoin de l'instancier pour les méthodes statiques. Vous pouvez donc passer la classe directement au premier argument d'invokePrivate et exécuter getDeclaredMethod.
Une classe pour regrouper les arguments requis pour exécuter une méthode privée avec les arguments ci-dessus.
Params.java
package com.example.demo.util;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
public class Params {
private List<Param> paramList;
public Params() {
paramList = new ArrayList<>();
}
/**
*Constructeur qui spécifie des arguments en même temps que l'initialisation.
* @param type
* @param arg
*/
public <T> Params(Class<T> type, T arg) {
this();
add(type, arg);
}
/**
*Définir les arguments et leurs types.
* @param type
* @param arg
*/
public <T> void add(Class<T> type, T arg) {
paramList.add(new Param(type, arg));
}
/**
*Renvoie le type d'argument défini sous forme de tableau.
* @return
*/
public Class<?>[] getTypes() {
Class<?>[] types = new Class[paramList.size()];
for (int i = 0; i < paramList.size(); i++) {
types[i] = paramList.get(i).getType();
}
return types;
}
/**
*Renvoie l'argument set sous forme de tableau.
* @return
*/
public Object[] getArgs() {
Object[] args = new Object[paramList.size()];
for (int i = 0; i < paramList.size(); i++) {
args[i] = paramList.get(i).getArg();
}
return args;
}
/**
*Classe représentant un argument.<br />
*Il a un objet argument et son type comme attributs.
*
*/
@Data
private class Param {
private Class<?> type;
private Object arg;
<T> Param(Class<T> type, T arg) {
this.type = type;
this.arg = arg;
}
}
}
Préparez une méthode privée avec un argument de manière appropriée.
Test.java
private String doSomthing(int i, Long l, String str){
System.out.println(Integer.toString(i));
System.out.println(l.toString());
System.out.println(str);
return "Terminé!";
}
UtilTest.java
@Test
public void test1() {
AService test = new AService();
//Essayez de spécifier le premier argument dans le constructeur
Params params = new Params(int.class, 1);
//Puis ajoutez avec ajouter
params.add(Long.class, 20L);
params.add(String.class, "Troisième argument");
try {
//Courir
String ret = (String) ReflectionUtil.invokePrivate(test, "doSomthing", params);
System.out.println(ret);
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
Lors de son utilisation, il est plus facile de voir invokePrivate s'il est importé statiquement.
Résultat d'exécution
1
20
Troisième argument
Terminé!
Au fait,
UtilTest.java
/**
*Lorsque null est spécifié au lieu de paramètres.
*/
@Test
public void testParamsNull() {
AServices = new AService();
try {
ReflectionUtil.invokePrivate(s, TARGET_METHOD, null);
fail();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*Lorsque les arguments définis dans les paramètres ne correspondent pas.
*/
@Test
public void testParamsInvalid() {
AService s = new AService();
Params params = new Params(int.class, 1);
params.add(Long.class, 20L);
try {
ReflectionUtil.invokePrivate(s, TARGET_METHOD, params);
fail();
} catch (Exception e) {
e.printStackTrace();
}
}
Test de résultat d'exécution()
java.lang.NullPointerException: params is required
at com.example.demo.util.ReflectionUtil.invokePrivate(ReflectionUtil.java:32)
at com.example.demo.UtilTest.test1(UtilTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
:
Test de résultat d'exécutionParamsInvalid()
java.lang.NoSuchMethodException: com.example.demo.service.AService.doSomthing(int, java.lang.Long)
at java.lang.Class.getDeclaredMethod(Class.java:2122)
at com.example.demo.util.ReflectionUtil.invokePrivate(ReflectionUtil.java:35)
at com.example.demo.UtilTest.test1(UtilTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
:
c'est tout.
Recommended Posts