package com.dc.fillmore;
import org.apache.log4j.Logger;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* A base test case for hibernate unit tests.
* This base test case serves two main purposes:
* <ul>
* <li>(1) extends Spring's <code>AbstractTransactionalDataSourceSpringContextTests</code>
* class, implementing the required method to give the name of the application context xml
* file. This superclass automagically sets up a spring context and calls setters on
* any subclass with service implementations. This way each unit test needs only extend this class
* and provide a setter for the service bean, as mapped in the application context (applicationContext.xml)
* </li>
* <li>(2) Sets up a dummy datasource mapped to a hard-coded JNDI string. We use Spring's
* SimpleNamingContextBuilder to set up a <code>DataSource</code> in a mock JNDI context,
* which points to an in-memory instance of HSQL, (a temporary testing database).
* Mocking JNDI like this allows us to use the same exact configuration we do in production,
* and switch out the database transparently! Hibernate automatically creates the schema on the fly,
* and the database dialect is set up in hibernate.properties (production and testing each
* have their own).
*
* </li>
* </ul>
*/
public abstract class HibernateBaseTestCase extends AbstractTransactionalDataSourceSpringContextTests {
private static final String JNDI_DATASOURCE_LOCATION = "java:comp/env/jdbc/DataSource";
private static final Logger log = Logger.getLogger(HibernateBaseTestCase.class);
static{
try {
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind(JNDI_DATASOURCE_LOCATION, new InMemoryHsqlDataSource());
builder.activate();
} catch (NamingException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
throw new RuntimeException(e);
} catch (IllegalStateException e) {
if (e.getMessage().indexOf("already set")<0) {
throw e;
} else {
// TODO: fix this so it only happens once - dont put in static block?
}
}
}
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
setComplete(); // signals no need for rollback,
// (as we don't care if we leave data in our
// ad-hoc/in-memory database instance!)
}
protected String[] getConfigLocations() { return new String[] {"applicationContext.xml"}; }
/**
* a dummy datasource that we bind to JNDI in a static block above.
*/
private static class InMemoryHsqlDataSource implements DataSource {
public InMemoryHsqlDataSource() {
try {
Class.forName("org.hsqldb.jdbcDriver");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("hsql not in classpath!",e);
}
}
public Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:hsqldb:mem:registration2005_temporaryTestDatabase",
"sa", "");
}
public Connection getConnection(String username, String password) throws SQLException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public PrintWriter getLogWriter() throws SQLException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setLogWriter(PrintWriter out) throws SQLException {
}
public void setLoginTimeout(int seconds) throws SQLException {
}
public int getLoginTimeout() throws SQLException {
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
}
}