jUnit has been around for a long time. But there are always better techniques to implement old ways. I have provided below an efficient junit aprroach integrated with DbUnit and Spring with support for transaction and hibernate open session. Significant features are:
- Integration with DbUnit: DbUnit puts database into a known state between test runs. Pre-loads database with known data set before the test
- Transaction support using spring: After each test all changes made by the test are rolled back. Hence there is no need to programatically undo channges made by the test. Much cleaner code. (Thanks, Jim)
- After each test, clear the pre-loaded data set from database
- Support for open session in view: Web applications using Hibernate with lazy loading need to keep the session open till the view is rendered. (Read more)
/**
* Junit test integrated with DbUnit and spring. Provides support for
* transaction and open session. This wraps each test method with a
* transaction and rollbacks after the method exits. DbUnit
* is used to load up the table with initial set of values.
*/
public class MyTest extends AbstractTransactionalDataSourceSpringContextTests {
private SessionFactory sessionFactory;
private Session session;
private static ConfigurableApplicationContext factory;
private final String[] TABLES = { “EmployeeTable”, “DepartmentTable” };
private final String DATA_FILE = “data.xml”;
private final String[] CONFIG_LOCATIONS = { “spring-context.xml” };
public static Test suite() {
return new TestSuite(MyTest.class);
}
protected String[] getConfigLocations() {
return CONFIG_LOCATIONS;
}
// This method is used to perform any setup operations, such as
// populating a database table, within the transaction.
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
if (factory == null) {
factory = new ClassPathXmlApplicationContext(getConfigLocations());
}
// Load test data using DBUnit
DataSource ds = (DataSource) factory.getBean(”dataSource”);
Connection con = DataSourceUtils.getConnection(ds);
IDatabaseConnection dbUnitCon = new DatabaseConnection(con);
IDataSet dataSet = new FlatXmlDataSet(Thread.currentThread().
getContextClassLoader().getResourceAsStream(DATA_FILE));
try {
DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dataSet);
} finally {
DataSourceUtils.releaseConnection(con, ds);
}
// Support of open session
sessionFactory = (SessionFactory) factory.getBean(”sessionFactory”);
session = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
protected void onTearDownAfterTransaction() throws Exception {
// delete table entries
deleteFromTables(TABLES);
// release session
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
session = holder.getSession();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.releaseSession(session, sessionFactory);
}
public void testSomething() throws Exception {
// …
}
}