ch.inftec.ju.testing.db.AbstractDbTest Maven / Gradle / Ivy
Show all versions of ju-testing Show documentation
package ch.inftec.ju.testing.db;
import java.lang.reflect.Method;
import javax.persistence.EntityManager;
import org.junit.After;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.inftec.ju.db.EmfWork;
import ch.inftec.ju.db.JuEmUtil;
import ch.inftec.ju.db.JuEmfUtil;
import ch.inftec.ju.util.TestUtils;
/**
* Base class for DB tests.
*
* Provides a machanism to evaluate the test DB at runtime, thus enabling DB tests
* targeting various DB implementations.
* @author Martin
*
*/
public class AbstractDbTest {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
protected EntityManager em;
protected JuEmUtil emUtil;
private JuEmfUtil emfUtil;
private EmfWork emfWork;
/**
* Rule to initialize DB fields. We need to use a rule so we can evaluate the method
* annotation.
*/
@Rule
public DbInitializerRule dbInitializer = new DbInitializerRule(this);
@After
public void cleanupDb() {
if (this.emfWork != null) {
this.emfWork.close();
this.emfWork = null;
this.em = null;
}
}
/**
* Sets the transaction to rollback.
*/
protected final void setRollbackOnly() {
this.emfWork.setRollbackOnly();
}
/**
* Starts a new EmfWork. The caller is responsible to close the work.
* @return EmfWork with a new transaction
*/
protected final EmfWork startNewWork() {
return this.emfUtil.startWork();
}
/**
* This method can be overridden by extending classes to run DB initialization scripts before the test is
* actually run.
*
* The method is self-responsible to release any resources aquired from the provided JuEmtUtil instance.
*
* The default implementation is empty.
* @param emfUtil JuEmfUtil instance that can be used to access the DB
*/
protected void runDbInitializationScripts(JuEmfUtil emfUtil) {
}
private static class DbInitializerRule implements TestRule {
private final AbstractDbTest dbTest;
DbInitializerRule(AbstractDbTest dbTest) {
this.dbTest = dbTest;
}
@Override
public Statement apply(final Statement base, final Description description) {
final Method method = TestUtils.getTestMethod(description);
// Evaluate Persistence Unit name
String persistenceUnit = "ju-pu-test";
String profile = null;
// Check if the persistenceUnit is overwritten by an annotation (method overrules
// class annotation)
JuDbTest juDbTest = method.getAnnotation(JuDbTest.class);
if (juDbTest == null) {
juDbTest = this.dbTest.getClass().getAnnotation(JuDbTest.class);
}
if (juDbTest != null) {
persistenceUnit = juDbTest.persistenceUnit();
profile = juDbTest.profile();
}
this.dbTest.emfUtil = new EmfUtilProvider().createEmfUtil(persistenceUnit, profile);
return new Statement() {
@Override
public void evaluate() throws Throwable {
// Run dbInitializationScripts
dbTest.runDbInitializationScripts(dbTest.emfUtil);
DbTestAnnotationHandler annotationHandler = new DbTestAnnotationHandler(method, description);
// Run preAnnotations in own transaction
try (EmfWork ew = dbTest.emfUtil.startWork()) {
annotationHandler.executePreTestAnnotations(ew.getEmUtil());
}
// Initialize protected fields of test class
dbTest.emfWork = dbTest.emfUtil.startWork();
dbTest.em = dbTest.emfWork.getEm();
dbTest.emUtil = new JuEmUtil(dbTest.em);
// Run test method
base.evaluate();
// Run post server code in own transaction
try (EmfWork ew = dbTest.emfUtil.startWork()) {
annotationHandler.executePostServerCode(ew.getEmUtil());
}
// Run postAnnotations in own transaction
try (EmfWork ew = dbTest.emfUtil.startWork()) {
annotationHandler.executePostTestAnnotations(ew.getEmUtil());
}
}
};
}
}
}