How are folks doing unit testing with Cayenne?
I should have asked before embarking on it, but I developed a simple
base class that constructs an in-memory HSQL database and sets up a
DataContext to it. This works, but my setUp could use some
improvement to avoid needing a domain node configuration file. I've
pasted my base class below. Very pleasantly, Cayenne's DbGenerator
(which I learned of through the <cdbgen> Ant task code; my philosophy
is that you can learn all you need about Java from Ant in some way!)
worked wonders!
I will also need to implement a TestSetup to only have the database
created one time once I get more test cases in place and the set up
time becomes too painful.
I have also pasted one of my prototype test cases below to show you
what I'm doing and solicit critique.
Thanks,
Erik
abstract public class DbTestCase extends TestCase {
public void setUp() throws Exception {
String baseDir = System.getProperty("cayenneConfigBaseDir");
// liberally borrowed from Cayenne's DbGeneratorTask
InputSource in = new InputSource(new File(baseDir,
"CollexDomainMap.map.xml").getAbsolutePath());
DataMap dataMap = new MapLoader().loadDataMap(in);
DbGenerator generator = new DbGenerator(new HSQLDBAdapter(),
dataMap);
generator.setShouldCreateFKConstraints(true);
generator.setShouldCreatePKSupport(true);
generator.setShouldCreateTables(true);
generator.setShouldDropPKSupport(true);
generator.setShouldDropTables(true);
DriverDataSource dataSource = new DriverDataSource(new jdbcDriver
(), "jdbc:hsqldb:mem:db", "sa", "");
generator.runGenerator(dataSource);
// Configure the Cayenne DataContext to use a test-only set up,
for an in-memory database
// TODO: create this configuration dynamically rather than
loading files, as there is duplication with the above
// setup with the adapter, map file name, and JDBC URL and
driver.
FileConfiguration conf = new FileConfiguration("cayenne.xml");
conf.addFilesystemPath(new File(baseDir, "test/"));
conf.addFilesystemPath(new File(baseDir));
Configuration.initializeSharedConfiguration(conf);
// Put the data context into a ThreadLocal just like the web
tier listener does, giving
// direct DB access to any code that needs it.
DataContext context = DataContext.createDataContext();
DataContext.bindThreadDataContext(context);
}
protected final DataContext getDataContext() {
return DataContext.getThreadDataContext();
}
}
public class UserTest extends DbTestCase {
public void setUp() throws Exception {
super.setUp();
User user = (User) getDataContext().createAndRegisterNewObject
(User.class);
user.setUsername("validuser");
user.setPassword("password");
getDataContext().commitChanges();
}
public void testLogin() {
User user = User.login("invalid", "password");
assertNull(user);
user = User.login("validuser", "password");
assertEquals("validuser", user.getUsername());
}
/**
* Tests that the custom Tapestry IMonitor will rollback changes
to the DataContext.
* An assumption is made that Tapestry will do the right thing and
fire to our monitor.
*/
public void testException() {
CollexMonitorFactory factory = new CollexMonitorFactory();
IMonitor monitor = factory.createMonitor(null); // WebRequest
parameter is not used by our monitor factory
User user = User.login("validuser", "password");
user.setPassword("something different");
// this is what happens if a Tapestry listener method throws an
exception
monitor.serviceException(new Exception("test"));
// ensure password has not been changed
assertEquals("password", user.getPassword());
}
}
This archive was generated by hypermail 2.0.0 : Tue May 03 2005 - 08:53:25 EDT