Skip to content

Instantly share code, notes, and snippets.

@mrg
Last active August 29, 2015 14:03
Show Gist options
  • Save mrg/430cd07017084431b2eb to your computer and use it in GitHub Desktop.
Save mrg/430cd07017084431b2eb to your computer and use it in GitHub Desktop.
Superclass for Cayenne/Tapestry unit testing using JNDI connections and allowing Cayenne to create the test database from the Cayenne Model. Designed for Cayenne 3.0 and Tapestry 5. See POM for additional dependencies.
...
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.178</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>simple-jndi</groupId>
<artifactId>simple-jndi</artifactId>
<version>0.11.4.1</version>
<scope>test</scope>
</dependency>
...
import java.io.File;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import your.test.TestModule;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.access.dbsync.CreateIfNoSchemaStrategy;
import org.apache.cayenne.conf.Configuration;
import org.apache.cayenne.conf.DefaultConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.RegistryBuilder;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
/**
* Abstract base class for unit tests. Provides Cayenne and Tapestry
* initialization.
*/
public abstract class TestBase
{
private static final Log log = LogFactory.getLog(TestBase.class);
private static final String JNDI_NAME = "jdbc/analytic-db";
private static final String SUBCONTEXT = "java:comp/env";
private static JdbcDataSource dataSource;
private static Context jndiContext;
private static Registry registry;
private DataContext dataContext;
// Initialize the JNDI Naming and create the context once.
static
{
try
{
// Configure System properties for using SimpleJNDI.
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.osjava.sj.memory.MemoryContextFactory");
System.setProperty("org.osjava.sj.jndi.shared", "true");
// Create JNDI context.
jndiContext = new InitialContext();
// Create sub-context.
jndiContext.createSubcontext(SUBCONTEXT);
}
catch (NamingException exception)
{
log.fatal("Could not create JNDI.", exception);
}
}
/**
* Sets up JNDI, Cayenne, Database, and Tapestry Registry for all tests.
*/
@BeforeClass
public static void setUpAllTests() throws NamingException
{
// Delete pre-existing test database if present. Filename is sensitive to version of H2 being used.
FileUtils.deleteQuietly(new File(FileUtils.getUserDirectory(), "adb-unit-tests.mv.db"));
// Create H2 database data source.
dataSource = new JdbcDataSource();
dataSource.setURL("jdbc:h2:~/adb-unit-tests");
dataSource.setUser("sa");
dataSource.setPassword("sa");
// Bind our H2 database data source to the JNDI context.
// NOTE: Must match Cayenne Model's JNDI name.
jndiContext.bind(JNDI_NAME, dataSource);
// Configure Cayenne to create the missing database schema.
DefaultConfiguration cayenneConfiguration = new DefaultConfiguration();
cayenneConfiguration.setSchemaUpdateStrategy(new CreateIfNoSchemaStrategy());
Configuration.initializeSharedConfiguration(cayenneConfiguration);
// Build the Tapestry Registry.
registry = RegistryBuilder.buildAndStartupRegistry(TestModule.class);
}
/**
* Closes the H2 DataSource, unbinds the DataSource from the JNDI, and shuts
* down the Tapestry Registry.
*
* @throws NamingException
* @throws SQLException
*/
@AfterClass
public static void tearDownAllTests() throws NamingException, SQLException
{
dataSource.getConnection().close();
jndiContext.unbind(JNDI_NAME);
registry.shutdown();
dataSource = null;
registry = null;
}
/**
* Sets up for individual unit tests. Every unit test gets a fresh Cayenne
* DataContext.
*/
@Before
public void setUpIndividualTests()
{
dataContext = CayenneUtils.createDataContext();
}
/**
* Resets the Cayenne DataContext after every test.
*/
@After
public void tearDownIndividualTests()
{
dataContext = null;
}
/**
* @return A Cayenne DataContext which can be used in unit tests.
*/
public DataContext getDataContext()
{
return dataContext;
}
/**
* @return A Cayenne ObjectContext which can be used in unit tests.
*/
public ObjectContext getObjectContext()
{
return dataContext;
}
/**
* @return The Tapestry Registry which can be used to "inject" services.
*/
public Registry getRegistry()
{
return registry;
}
/**
* Creates a new Cayenne object.
*
* @param persistentClass
* The class to instantiate.
* @return A new object in the unit test DataContext.
*/
public <T> T newCayenneObject(Class<T> persistentClass)
{
return getDataContext().newObject(persistentClass);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment