Created
July 4, 2019 19:13
-
-
Save jenslohmann/339aa7d539d0e419e2307de4679dbf50 to your computer and use it in GitHub Desktop.
Helper class for injecting objects when not in a Dependency Injection context - typically when unit testing.
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 dk.jlo.util; | |
import java.lang.reflect.Field; | |
/** | |
* Injects an object into a (private) field in a bean; primarily for poor man's injection for unit testing when not running in a Dependency Injection environment.<p> | |
* Travels through super classes if necessary.<p> | |
* Usage: | |
* <pre> | |
* import static dk.jlo.util.PoorMansInjector.inject; | |
* [...] | |
* inject(object).intoField("fieldName").inBean(bean); | |
* </pre> | |
*/ | |
@SuppressWarnings("unused") | |
public class PoorMansInjector { | |
/** | |
* Instantiates the injector. | |
* | |
* @param object the object to be injected. | |
* @return The injector. | |
*/ | |
public static FieldInjector inject(Object object) { | |
return new FieldInjector(object); | |
} | |
public static class FieldInjector { | |
private Object object; | |
FieldInjector(Object object) { | |
this.object = object; | |
} | |
/** | |
* Tells the injector where to inject the previously given object. | |
* | |
* @param privateFieldName the (usually private) field in question. | |
* @return The injector. | |
*/ | |
public FinalInjector intoField(String privateFieldName) { | |
FinalInjector finalInjector = new FinalInjector(object, privateFieldName); | |
object = null; | |
return finalInjector; | |
} | |
} | |
public static class FinalInjector { | |
private Object object; | |
private String privateFieldName; | |
FinalInjector(Object object, String privateFieldName) { | |
this.object = object; | |
this.privateFieldName = privateFieldName; | |
} | |
/** | |
* Performs the injection. | |
* | |
* @param bean the bean/object containing the field. | |
* @throws IllegalAccessException in case the injection is somehow not possible even after setting the field accessible. | |
* @throws NoSuchFieldException in case the field is not found in the class or superclass(es). | |
*/ | |
public void inBean(Object bean) throws IllegalAccessException, NoSuchFieldException { | |
Field beanField = getFieldInClassHierarchy(bean, privateFieldName); | |
beanField.setAccessible(true); | |
beanField.set(bean, object); | |
object = null; | |
privateFieldName = null; | |
} | |
private Field getFieldInClassHierarchy(Object bean, String fieldName) throws NoSuchFieldException { | |
Field beanField = null; | |
Class<?> aClass = bean.getClass(); | |
do { | |
try { | |
beanField = aClass.getDeclaredField(fieldName); | |
} catch (NoSuchFieldException e) { | |
aClass = aClass.getSuperclass(); | |
if (aClass == null) { | |
throw e; | |
} | |
} | |
} while (beanField == null); | |
return beanField; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment