Saturday, June 2, 2007

Maven 2 + Hibernate + HSQLDB (project contained integration testing for Hibernate)

The problem:

You must check your Hibernate objects against a database for testing purposes. This database is somewhere on your network, and accessible to many of your fellow co-workers. You cannot expect anything to stay static in this db, which means eventually your tests will fail.

A solution:

Maven can make projects very portable. Hibernate makes working with persistent objects simple. HSQLDB is a Java database that you can run embeded in other programs.

A problem with using Hibernate is it can take away some of the portability of your project. This happens because you must provide a database for making your objects persistent. In doing so your test configuration files will be spec'd to a single database. What happens when someone runs the project's tests and does not have access to the test database? The tests will fail :( We want to have unit tests be used for all our hibernate objects. It is especially important to thoroughly test them, as they will be a central part of your projects functioning properly (especially web projects!).

Luckily Maven makes it easy to use one database for testing, and another for production. This is where HSQLDB can come in handy. You can create a hibernate config just for testing which connects to an in memory HSQL database. You will need the proper files in src/test/resources folder of your Maven 2 project. The files include the test version of your hibernate config file. I put the hibernate mapping files into folders that mirror the packaging of the POJO object classes. When you run 'mvn package' the .hbm files will be placed in the same folder as the POJO class they belong to. Here is an example of my Maven 2 project's structure:

/project
pom.xml
...other files
/src
/main
/java
/some
/package
Foo.java
/resources
hibernate.cfg.xml
/some
/package
Foo.hbm.xml
/test
/java
/some
/testpackage
TestFoo.java
/resources
hibernate.cfg.xm

So you can see that there are a hibernate configuration file for the build and the test phase. Now in the test hibernate.cfg.xml file you will need to have the following properties set:


<!-- Database connection settings -->
<!-- HSQL DB -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:mem:aname</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>

and...

<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<mapping resource="some/package/Foo.hbm.xml" />


These entries should have you now set up to use a in memory database for all your testing with hibernate. But before this will work you need to do one more thing.

Set up you Maven 2 project so that HSQLDB is a dependency. Added this dependency section to your project:

<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.1</version>
</dependency>

Note that you will not need to make any specific JDBC driver available. The HSQLDB dependency contains the proper driver!

Using this recipe you will be able to make very portable Maven/Hibernate projects. Users any place in the world will be able to check out your project and test it immediately. If they would like to test using their own database it is not hard for them to overwrite what is in the src/test/hibernate.cfg.xml file.