Created
May 12, 2014 08:52
-
-
Save diversit/229ab1c5b42e74893923 to your computer and use it in GitHub Desktop.
Test util for to easily set private/hidden fields on objects. Supports mocked types.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nl.malmberg.test.utils; | |
import java.lang.reflect.Field; | |
/** | |
* Helper class for setting properties via reflection. | |
* Based on Deencapsulation class of JMockit. | |
*/ | |
public class Deencapsulation { | |
private Deencapsulation() {} | |
public static void setField(Object objectWithField, Object fieldValue) { | |
final Field field = getFieldForType(objectWithField.getClass(), fieldValue.getClass()); | |
setField(objectWithField, fieldValue, field); | |
} | |
public static void setField(Object objectWithField, String fieldName, Object fieldValue) { | |
final Field field = getField(objectWithField, fieldName); | |
setField(objectWithField, fieldValue, field); | |
} | |
/** | |
* @param classWithFieldClass | |
* @param fieldClass | |
* @return First field with fieldClass in classWithFieldClass or <code>null</code> if no field found. | |
*/ | |
private static Field getFieldForType(Class<?> classWithFieldClass, Class<?> fieldClass) { | |
Class<?> wantedType = getRealClassType(fieldClass); | |
for(Field declaredField : classWithFieldClass.getDeclaredFields()) { | |
if(declaredField.getType().equals(wantedType)) { | |
return declaredField; | |
} | |
} | |
// not found (yet) | |
if(classWithFieldClass.getSuperclass() != null) { | |
return getFieldForType(classWithFieldClass.getSuperclass(), wantedType); | |
} else { | |
return null; | |
} | |
} | |
/** | |
* Get the real class type in case a mock class is used. | |
* @param fieldClass | |
* @return The real class type. | |
*/ | |
private static Class<?> getRealClassType(Class<?> fieldClass) { | |
if(isMockedClass(fieldClass)) { | |
String classname = fieldClass.getName(); | |
String typename = classname.substring(0, classname.indexOf("$$")); | |
try { | |
return Class.forName(typename); | |
} catch (ClassNotFoundException e) { | |
throw new RuntimeException("Cannot find class for wantedType "+typename, e); | |
} | |
} else { | |
return fieldClass; | |
} | |
} | |
/** | |
* Assumes a mocked classname contains '$$'. | |
* @param aClass | |
* @return <code>true</code> if is a mocked class. | |
*/ | |
private static boolean isMockedClass(Class<?> aClass) { | |
return aClass.getName().contains("$$"); | |
} | |
/** | |
* Set value on field. | |
* @param objectWithField | |
* @param fieldValue | |
* @param field | |
*/ | |
private static void setField(Object objectWithField, Object fieldValue, Field field) { | |
if(field == null) { | |
throw new RuntimeException("No field available to set value on."); | |
} | |
field.setAccessible(true); | |
try { | |
field.set(objectWithField, fieldValue); | |
} catch (IllegalAccessException e) { | |
throw new RuntimeException(String.format("Error setting value for field %s on object %s.", field.getName(), objectWithField), e); | |
} | |
} | |
/** | |
* @param objectWithField | |
* @param fieldName | |
* @return the field of objectWithField (or superclass) by fieldName or null if field could not be found. | |
*/ | |
private static Field getField(Object objectWithField, String fieldName) { | |
return getField(objectWithField.getClass(), fieldName); | |
} | |
/** | |
* @param objectClass | |
* @param fieldName | |
* @return the field of objectClass (or superclass) by fieldName or null if field could not be found. | |
*/ | |
private static Field getField(Class<?> objectClass, String fieldName) { | |
Field declaredField = null; | |
try { | |
declaredField = objectClass.getDeclaredField(fieldName); | |
} catch (NoSuchFieldException e) { | |
// might fail | |
} catch (SecurityException e) { | |
// might fail | |
} | |
if(declaredField == null && objectClass.getSuperclass() != null) { | |
return getField(objectClass.getSuperclass(), fieldName); | |
} else { | |
return declaredField; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment