HHH-6014: A JUnit test runner for Envers, which uses the CustomTestRunner and wraps it with a Parametrized test runner, so that tests are run with two audit strategies

This commit is contained in:
adamw 2011-04-01 21:35:53 +02:00
parent 285da70a25
commit 26b5e1afa8
5 changed files with 171 additions and 40 deletions

View File

@ -27,28 +27,27 @@ import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.TransactionManager;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.BeforeClassOnce;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.hibernate.cfg.Environment;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.event.EnversIntegrator;
import org.hibernate.service.internal.BasicServiceRegistryImpl;
import org.junit.runners.Parameterized;
/**
* @author Adam Warski (adam at warski dot org)
*/
public abstract class AbstractEntityTest {
public abstract class AbstractEntityTest extends AbstractEnversTest {
private EntityManagerFactory emf;
private EntityManager entityManager;
private AuditReader auditReader;
@ -65,7 +64,7 @@ public abstract class AbstractEntityTest {
}
}
@BeforeMethod
@Before
public void newEntityManager() {
closeEntityManager();
@ -76,10 +75,9 @@ public abstract class AbstractEntityTest {
}
}
@BeforeClass
@Parameters("auditStrategy")
public void init(@Optional String auditStrategy) throws IOException {
init(true, auditStrategy);
@BeforeClassOnce
public void init() throws IOException {
init(true, getAuditStrategy());
}
protected void init(boolean audited, String auditStrategy) throws IOException {
@ -108,7 +106,7 @@ public abstract class AbstractEntityTest {
newEntityManager();
}
@AfterClass
@AfterClassOnce
public void close() {
closeEntityManager();
emf.close();

View File

@ -0,0 +1,29 @@
package org.hibernate.envers.test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.List;
/**
* An abstract Envers test which runs the tests using two audit strategies.
* @author Adam Warski (adam at warski dot org)
*/
@RunWith(EnversRunner.class)
public class AbstractEnversTest {
private String auditStrategy;
@Parameterized.Parameters
public static List<Object[]> data() {
return Arrays.asList(new Object[]{null}, new Object[]{"org.hibernate.envers.strategy.ValidityAuditStrategy"});
}
public void setTestData(Object[] data) {
auditStrategy = (String) data[0];
}
public String getAuditStrategy() {
return auditStrategy;
}
}

View File

@ -10,12 +10,10 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.junit.Before;
/**
* Base class for testing envers with Session when the same session and
@ -24,23 +22,20 @@ import org.testng.annotations.Parameters;
* @author Hern&aacute;n Chanfreau
*
*/
public abstract class AbstractOneSessionTest {
public abstract class AbstractOneSessionTest extends AbstractEnversTest {
protected Configuration config;
private ServiceRegistry serviceRegistry;
private SessionFactory sessionFactory;
private Session session ;
private AuditReader auditReader;
@BeforeClass
@Parameters("auditStrategy")
public void init(@Optional String auditStrategy) throws URISyntaxException {
@BeforeClassOnce
public void init() throws URISyntaxException {
config = new Configuration();
URL url = Thread.currentThread().getContextClassLoader().getResource(getHibernateConfigurationFileName());
config.configure(new File(url.toURI()));
String auditStrategy = getAuditStrategy();
if (auditStrategy != null && !"".equals(auditStrategy)) {
config.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
}
@ -62,7 +57,7 @@ public abstract class AbstractOneSessionTest {
return sessionFactory;
}
@AfterClass
@AfterClassOnce
public void closeSessionFactory() {
try {
sessionFactory.close();
@ -79,7 +74,7 @@ public abstract class AbstractOneSessionTest {
* Creates a new session and auditReader only if there is nothing created
* before
*/
@BeforeMethod
@Before
public void initializeSession() {
if (getSession() == null) {
session = getSessionFactory().openSession();

View File

@ -10,12 +10,10 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.junit.Before;
/**
* Base class for testing envers with Session.
@ -23,7 +21,7 @@ import org.testng.annotations.Parameters;
* @author Hern&aacute;n Chanfreau
*
*/
public abstract class AbstractSessionTest {
public abstract class AbstractSessionTest extends AbstractEnversTest {
protected Configuration config;
private ServiceRegistry serviceRegistry;
@ -32,13 +30,13 @@ public abstract class AbstractSessionTest {
private AuditReader auditReader;
@BeforeClass
@Parameters("auditStrategy")
public void init(@Optional String auditStrategy) throws URISyntaxException {
@BeforeClassOnce
public void init() throws URISyntaxException {
config = new Configuration();
URL url = Thread.currentThread().getContextClassLoader().getResource(getHibernateConfigurationFileName());
config.configure(new File(url.toURI()));
String auditStrategy = getAuditStrategy();
if (auditStrategy != null && !"".equals(auditStrategy)) {
config.setProperty("org.hibernate.envers.audit_strategy", auditStrategy);
}
@ -61,13 +59,13 @@ public abstract class AbstractSessionTest {
}
@BeforeMethod
@Before
public void newSessionFactory() {
session = getSessionFactory().openSession();
auditReader = AuditReaderFactory.get(session);
}
@AfterClass
@AfterClassOnce
public void closeSessionFactory() {
try {
sessionFactory.close();

View File

@ -0,0 +1,111 @@
package org.hibernate.envers.test;
import org.hibernate.testing.junit4.CustomRunner;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.TestClass;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Copied & modified from {@link org.junit.runners.Parameterized}.
*
* The modification is that the generated runners extend {@link CustomRunner} instead of the default
* {@code TestClassRunnerForParameters}.
*
* The runner itself sets the data using a setter instead of a constructor, and creates only one test instance. Moreover
* it doesn't override {@code classBlock} which causes the custom {@code @BeforeClassOnce} and {@code @AfterClassOnce}
* annotations to work.
* @author Adam Warski (adam at warski dot org)
*/
public class EnversRunner extends Suite {
private class TestClassCustomRunnerForParameters extends CustomRunner {
private final int fParameterSetNumber;
private final List<Object[]> fParameterList;
TestClassCustomRunnerForParameters(Class<?> type, List<Object[]> parameterList, int i)
throws InitializationError, NoTestsRemainException {
super(type);
fParameterList= parameterList;
fParameterSetNumber= i;
}
@Override
protected Object getTestInstance() throws Exception {
Object testInstance = super.getTestInstance();
((AbstractEnversTest) testInstance).setTestData(computeParams());
return testInstance;
}
private Object[] computeParams() throws Exception {
try {
return fParameterList.get(fParameterSetNumber);
} catch (ClassCastException e) {
throw new Exception(String.format(
"%s.%s() must return a Collection of arrays.",
getTestClass().getName(), getParametersMethod(
getTestClass()).getName()));
}
}
@Override
protected String getName() {
return String.format("[%s]", fParameterSetNumber);
}
@Override
protected String testName(final FrameworkMethod method) {
return String.format("%s[%s]", method.getName(),
fParameterSetNumber);
}
}
private final ArrayList<Runner> runners= new ArrayList<Runner>();
/**
* Only called reflectively. Do not use programmatically.
*/
public EnversRunner(Class<?> klass) throws Throwable {
super(klass, Collections.<Runner>emptyList());
List<Object[]> parametersList= getParametersList(getTestClass());
for (int i= 0; i < parametersList.size(); i++)
runners.add(new TestClassCustomRunnerForParameters(getTestClass().getJavaClass(),
parametersList, i));
}
@Override
protected List<Runner> getChildren() {
return runners;
}
@SuppressWarnings("unchecked")
private List<Object[]> getParametersList(TestClass klass)
throws Throwable {
return (List<Object[]>) getParametersMethod(klass).invokeExplosively(
null);
}
private FrameworkMethod getParametersMethod(TestClass testClass)
throws Exception {
List<FrameworkMethod> methods= testClass.getAnnotatedMethods(Parameterized.Parameters.class);
for (FrameworkMethod each : methods) {
int modifiers= each.getMethod().getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
return each;
}
throw new Exception("No public static parameters method on class "
+ testClass.getName());
}
}