views:

38

answers:

3

I'm writing some integration tests for a Spring/Hibernate app I'm working on, and I would like to to test things with as close to real conditions as possible, which includes using Hibernate's second level cache and committing transactions.

I was wondering if there was an efficient way to ask Hibernate to delete everything from the database and the caches. The best I could come up with was using an HQL "delete from XImpl" line for every type of object, but I have a couple dozen domain objects, and it feels like there should be a better way.

A: 

Taking Pascal's approach above, I went looking for the right way to create a SchemaUpdate object in Spring and realized that I didn't need to. Instead, I can just get ahold of Spring's sessionFactory object for Hibernate and ask it to drop/create the schema. Combining that with the rest of Pascal's solution, we get this:

LocalSessionFactoryBean localSessionFactoryBean = (LocalSessionFactoryBean)appContext.getBean("&sessionFactory");
localSessionFactoryBean.dropDatabaseSchema();
localSessionFactoryBean.createDatabaseSchema();
Cache cache = sf.getCache();
cache.evictEntityRegions();
cache.evictCollectionRegions();
cache.evictQueryRegions();

This is quite effective. The only downside is that (at least for me) it's markedly slower than calling "delete from obj1","delete from obj2" on each table name. Still, I like not having to repeat myself.

CaptainAwesomePants
+4  A: 

For the database, use the SchemaExport tool to recreate the schema:

Configuration cfg = ....;
new SchemaExport(cfg).create(false, true);

For the 2nd level cache, get access to the underlying cache regions from the SessionFactory and evict everything:

SessionFactory sf = ...;
Cache cache = sf.getCache();
cache.evictEntityRegions();
cache.evictCollectionRegions();
cache.evictQueryRegions();

For the 1st level cache, well, simply get a new Session or call session.clear().

Pascal Thivent
SchemaExport! Awesome idea -- I'll give it a try on Monday.
CaptainAwesomePants
A: 

Take a look at Unitils. It has great support for database testing (using DbUnit) that we've been using for quite a while. It's really flexible, so you can use it if you ever find the need to pre-load data into the database for particular unit tests.

With Unitils, you'll create a dataset file (empty-db.xml) representing the empty database:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <obj1/>
  <obj2/>
</dataset>

On the classes or tests where you need to configure the data set

@DataSet("empty-db.xml")

We have a common base class for all persistence tests, so we were able to put the annotation in just one place.

The down side is that you will have to add lines to this file every time you add entities to Hibernate. And you have to get the order right to be consistent with foreign key constraints. We ended up adding a unit test to check this file against the Hibernate configuration to keep it in check.

The up side, especially for a large schema, is that it's way faster than rebuilding the schema.

dave