In Java, call private scope fields, methods, inner classes from the outside, Let's test it with JUnit.
First, let's try testing with JUnit.
There is a compilation error. It is a specification. Cannot be executed. Since it is private, it cannot be called in the same way as public.
So we use Reflection to call something private scope.
Reflection is a type of Java standard library. It is dealing with information about the class itself. As a concrete example With a string of class name, method name, field name Generate that class, execute methods, access fields I can do it.
The following is an external site, but it looks like this, for example. http://java.keicode.com/lang/reflection.php
"If it's so convenient, use it positively." You may think that. However, Reflection is a double-edged sword. Be careful when handling. ** But I will introduce it. ** **
Reflection depends on how you use it
--Class design collapses --Code is hard to write and hard to read --Performance is worse than calling a method normally
There are also problems such as. ** But I will introduce it. ** **
"Test private scope with JUnit" This is because it is used for a limited purpose.
Let's fix the JUnit test class, which is full of errors.
package jp.co.illmatics.sample;
/**
*Class to be tested
*/
@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;
/**
*Test class
*/
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);
}
}
I was able to fix it.
Test
It's done.
Recommended Posts