Spring and DBUnit Integration
Posted on October 24, 2004 by Scott Leberknight
On a new project I'm working on, we are using Hibernate as the persistence framework and Spring for DAOs using its HibernateDaoSupport
class, declarative transaction management, and integration with Struts, among other things. We wanted to effectively unit test the persistent classes without writing the boilerplate code in our tests to insert and clean up test data. In the past I've written my own DBUnit-like framework, nowhere near as extensive, but it did the job. This time I decided to try DBUnit.
It took all of about 15 minutes to download, install, and get DBUnit integrated into our development environment. In DBUnit you subclass DatabaseTestCase
, override two methods, getConnection()
and getDataSet()
, and provide test data in XML files. I didn't want all our developers to have to actually implement these methods every time they write a database-driven test case, so I extended DatabaseTestCase
with the help of Spring to create default implementations of these methods in a BaseDatabaseTestCase
. Spring is used to mainly to configure a DataSource
from which a connection is obtained, in a dbunitContext.xml
file which resides in the same package as BaseDatabaseTestCase
. So the getConnection()
method simply obtains the DataSource
from the Spring application context defined in the XML file.
This solves the connection problem for all tests, but what about the dataset needed by DBUnit to prime the database prior to test execution? The dbunitContext.xml
permits you to define a standard set of files containing DBUnit datasets that all extending tests will get by default. This is optional and should not be used to have the entire database populated before each test. You could use it for populating some tables that are required to always be populated in your application, such as reference tables or user tables or something similar.
The BaseDatabaseTestCase
implements getDataSet()
to combine the DataSet found in the Spring application context with a default DataSet for the specific test. This default DataSet is defined in an XML file that resides in the same package as the test and is named the same as the test with the file extension .dbunit.xml
. For example, suppose you have a test MyTest.java
which extends BaseDatabaseTestCase
. Then to define the default DataSet for this test, simply create a file named MyTest.dbunit.xml
in the same package as MyTest. BaseDatabaseTestCase
automatically looks for this file and loads the DataSet contained within it. If there are any standard DataSets defined in dbunitContext.xml
, they are combined with the default DataSet to prime the database for the test.
This allows developers who need to create unit tests for database-driven code to simply extend BaseDatabaseTestCase
, write an XML file containing the test data, and implement standard JUnit testXXX()
methods. Pretty nifty.