Appeler des champs, des méthodes et des classes internes de portée privée en externe en Java Testons-le avec JUnit.
Tout d'abord, essayons de tester avec JUnit.
Il y a une erreur de compilation. C'est une spécification. Ne peut pas être exécuté. Puisqu'il est privé, il ne peut pas être appelé de la même manière que public.
Nous utilisons donc Reflection pour appeler quelque chose de portée privée.
Reflection est une sorte de bibliothèque standard Java. Il s'agit d'informations sur la classe elle-même. Comme exemple concret Avec une chaîne de nom de classe, nom de méthode et nom de champ Générer cette classe, exécuter des méthodes, accéder aux champs Je peux le faire.
Ce qui suit est un site externe, mais il ressemble à ceci, par exemple. http://java.keicode.com/lang/reflection.php
"Si c'est si pratique, utilisez-le de manière positive." Vous pouvez penser cela. Cependant, la réflexion est une épée à double tranchant. Soyez prudent lors de la manipulation. ** Mais je vais le présenter. ** **
La réflexion dépend de la façon dont vous l'utilisez
Il existe également des problèmes tels que. ** Mais je vais le présenter. ** **
"Tester l'étendue privée avec JUnit" C'est parce qu'il est utilisé dans un but limité.
Corrigeons la classe de test JUnit, qui regorge d'erreurs.
package jp.co.illmatics.sample;
/**
*Classe à tester
*/
@SuppressWarnings("unused")
public class PrivateSample {
private String field = "Hello field!";
private final String finalField = "Hello final field!";
private String doIt() {
return "Hello method!";
}
private class InnerClass {
public InnerClass() {
}
public String getInnerMethod() {
return "Hello inner method!";
}
}
}
package jp.co.illmatics.sample;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
import junit.framework.TestCase;
/**
*Classe d'essai
*/
public class PrivateSampleTest extends TestCase {
PrivateSample privateSample = new PrivateSample();
String expected = "";
String actual = "";
@Test
public void testField() throws Exception {
final String fieldName = "field";
expected = "Hello field!";
actual = (String) getFieldValue(privateSample, fieldName);
assertEquals(expected, actual);
}
@Test
public void testFinalField() throws Exception {
final String finalFieldName = "finalField";
expected = "Hello updated final Field!";
actual = (String) getUpdatedFinalFieldValue(privateSample, expected, finalFieldName);
assertEquals(expected, actual);
}
@Test
public void testMethod() throws Exception {
final String methodName = "doIt";
expected = "Hello method!";
actual = (String) getMethodValue(privateSample, methodName);
assertEquals(expected, actual);
}
@Test
public void testInnerClassMethod() throws Exception {
final String innerClassName = "jp.co.illmatics.sample.PrivateSample$InnerClass";
final String innerMethodName = "getInnerMethod";
expected = "Hello inner method!";
actual = (String) getInnerClassMethod(privateSample, innerClassName, innerMethodName);
assertEquals(expected, actual);
}
private Object getFieldValue(PrivateSample privateSample, String fieldName)
throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
SecurityException {
return getPrivateField(privateSample, fieldName).get(privateSample);
}
private Field getPrivateField(PrivateSample privateSample, String fieldName)
throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException {
Class<?> clazz = privateSample.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
}
private Object getUpdatedFinalFieldValue(PrivateSample privateSample, String newValue,
String fieldName) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
Field finalField = getPrivateField(privateSample, fieldName);
finalField.set(privateSample, newValue);
return finalField.get(privateSample);
}
private Object getMethodValue(PrivateSample privateSample, String name)
throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Method doIt = PrivateSample.class.getDeclaredMethod(name);
doIt.setAccessible(true);
return doIt.invoke(privateSample);
}
private Object getInnerClassMethod(PrivateSample parent, String classFullName,
String methodName) throws ClassNotFoundException, NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> innerClazz = loader.loadClass(classFullName);
Constructor<?> constructor = innerClazz.getDeclaredConstructor(parent.getClass());
constructor.setAccessible(true);
Object innerObj = constructor.newInstance(parent);
return innerClazz.getDeclaredMethod(methodName).invoke(innerObj);
}
}
J'ai pu le réparer.
Tester
C'est fait.
Recommended Posts