[JAVA] Créer un utilitaire de réflexion ①

introduction

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.

Méthode pour exécuter une méthode privée

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.

Classe qui résume les arguments

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;
		}
	}
}

Essayez de courir

Méthode privée à tester

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é!";
	}

cas de test

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

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

Créer un utilitaire de réflexion ②
Créer un utilitaire de réflexion ③
Créer un utilitaire de réflexion ①
[Java] Rendez-le constant
Faire un diamant en utilisant Java
Créez un labyrinthe de fouilles avec Ruby2D
Faites une langue! (Faire une simple calculatrice ②)
Essayez de faire un simple rappel
Créer un outil de diaporama avec JavaFX
Comment créer un conteneur Java
Comment créer un pilote JDBC
Priority Queue max En faire une file d'attente
Faites une langue! (Construction de l'environnement Java CC)
Faire un rappel de garbage avec line-bot-sdk-java
Créer une carte de liste avec LazyMap
Un murmure sur la classe utilitaire
Comment créer un écran de démarrage
Comment créer un plug-in Jenkins
Comment faire un projet Maven
Faire un appel SOAP en C #
Essayez de créer un itérateur qui puisse être vu
Comment créer un tableau Java
Faites un jeu de frappe avec ruby
Comment créer un résumé de calendrier Java
Notez les arguments de mot-clé Ruby
Faisons une carte de Noël avec Processing!
Faites une liste de choses à faire en famille avec Sinatra
Comment créer un robot Discord (Java)
Faites une liste de choses à faire en famille avec Sinatra
Créez quand même une fonction de connexion avec Rails
[docker] [nginx] Créer un ALB simple avec nginx
[Java] Créons une bibliothèque d'accès à la base de données!