
io.probedock.junitee.finder.FinderManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of junitee-data-utils Show documentation
Show all versions of junitee-data-utils Show documentation
JUnit data utilities to manage data in a database when doing tests like API tests against an
application in application server.
The newest version!
package io.probedock.junitee.finder;
import io.probedock.junitee.annotations.Finder;
import io.probedock.junitee.generator.DataGeneratorManager;
import io.probedock.junitee.dependency.DependencyInjector;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import io.probedock.junitee.utils.EntityManagerHolder;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* The finder manager keep track of factories to ensure only one finder type
* is instantiated during a class test execution.
*
* This finder manager should be used associated with a JUnit Rule mechanism.
*
* @author Laurent Prevost
*/
public class FinderManager implements TestRule {
private static final Logger LOG = Logger.getLogger(DataGeneratorManager.class.getCanonicalName());
/**
* Entity manager holder to manage the entity managers and their factories
*/
private EntityManagerHolder entityManagerHolder;
/**
* Keep track of the finders
*/
private Map finders = new HashMap<>();
/**
* Force the construction of the data generator with an one or more entity manager factory
*
* @param entityManagerHolder Entity manager holder to use
*/
public FinderManager(EntityManagerHolder entityManagerHolder) {
if (!entityManagerHolder.isReady()) {
throw new IllegalArgumentException("The entity manager holder must be ready. Call build() on holder to make it ready.");
}
this.entityManagerHolder = entityManagerHolder;
}
@Override
public Statement apply(Statement base, Description description) {
return internalApply(base, description);
}
/**
* Method to avoid problems with anonymous class and final variables otherwise
* the content of this method can be put on the method apply
*/
public Statement internalApply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
manageFinders(description);
base.evaluate();
}
};
}
/**
* Be able to retrieve a finder
*
* @param Finder type
* @param finderClass The finder class to lookup
* @return The finder found, null otherwise
*/
@SuppressWarnings("unchecked")
public T getFinder(Class finderClass) {
return (T) finders.get(finderClass);
}
/**
* Instantiate the finders
*
* @param description The description to get test data
* @throws Throwable Any errors
*/
private void manageFinders(Description description) throws FinderException {
// Clear the finders used in a previous test. Clear must be there because
// there is no warranty to reach the after if a test fails.
finders.clear();
Finder finderAnnotation = description.getAnnotation(Finder.class);
if (finderAnnotation == null) {
return;
}
// Retrieve all the data generators defined for the test method.
for (Class extends IFinder> finderClass : finderAnnotation.value()) {
// Retrieve the entity manager corresponding to the finder
EntityManager entityManager = entityManagerHolder.retrieveEntityManagerFromFinder(finderClass);
// Check if the data generator is already instantiated.
if (!finders.containsKey(finderClass)) {
// Instantiate a new data generator, inject the DAO and keep track of it.
finders.put(finderClass, (IFinder) Enhancer.create(finderClass, new Class[] {IFinder.class}, new FinderCallback(entityManager)));
}
else {
LOG.log(Level.SEVERE, "The finder [" + finderClass.getCanonicalName() + "] is already instantiated. One instance of each finder is allowed.");
throw new FinderException("The finder " + finderClass.getCanonicalName() + " is already registered. "
+ "Only one instance of each finder can be specified in the annotation.");
}
}
}
/**
* Callback class to allow lazy instantiation of annotated fields
*/
private static class FinderCallback implements MethodInterceptor {
/**
* Cache the fact that a the real implementation is injected or not
*/
private boolean injected = false;
/**
* Keep track of the entity manager to allow the management of the cache
*/
private EntityManager em;
/**
* Constructor
*
* @param em The entity manager
*/
public FinderCallback(EntityManager em) {
this.em = em;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// Lazy injection
if (!injected) {
DependencyInjector.inject(obj, em, false);
}
// Clear the entity manager cache if a find method is called
if (method.getName().startsWith("find")) {
em.clear();
}
// Invoke the method
return proxy.invokeSuper(obj, args);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy