Tuesday, 8 March 2011

Testing JPA Entities using DBUnit

DBUnit is a powerful testing tool that allows you to put your database into a known state in between tests. A common problem (and one of poor test design) is where a test changes the state of an object and this state affects the testing of objects in later tests. Each test should be independent and tests within a suite should be able to run in any order. This post will aim to describe the code needed to setup a database before each run of a JUnit test method.

The below class has three key methods:
  • initEntityManager() - this method is annotated with @BeforeClass so will only be called once for this test and called before any tests are run. The method will create an entity manager, get a connection to an instance of the in memory Java database HSQL and then populate it by reading in the flat xml database record structure that is contained in the file test-dataset.xml. For alternative dataset formats please visit http://www.dbunit.org/apidocs/org/dbunit/dataset/IDataSet.html
  • closeEntityManager() - this method is annotated with @AfterClass so will only be called once for this test and called after all the tests have been run. The method will close down the entity manager and the entity manager connection factory.
  • cleanDB() - this method is annotated with @Before and will be called before every test method call. The call to  DatabaseOperation.CLEAN_INSERT.execute will clean the database tables and insert the records from the dataset xml file. Database operations other than CLEAN_INSERT are described below:
            UPDATE        updates the database using the data in the dataset.
            INSERT         inserts the data in the dataset into the database.
            DELETE         deletes only the data in the dataset from the database.
            DELETE_ALL deletes all rows of tables present in the specified dataset.
            TRUNCATE   truncate tables listed in the dataset.
            REFRESH     refreshes the database using the data in the dataset.
            NONE           does what it says, nothing.

import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.impl.SessionImpl;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;

public class JPATest {

    protected static EntityManagerFactory entityManagerFactory;
    protected static EntityManager entityManager;
    protected static IDatabaseConnection connection;
    protected static IDataSet dataset;

    public static void initEntityManager() throws Exception {
        entityManagerFactory = Persistence.createEntityManagerFactory("PersistenceUnit");
        entityManager = entityManagerFactory.createEntityManager();
        connection = new DatabaseConnection(((SessionImpl)(entityManager.getDelegate())).connection());
        connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory());

        FlatXmlDataSetBuilder flatXmlDataSetBuilder = new FlatXmlDataSetBuilder();
        dataset = flatXmlDataSetBuilder.build(

    public static void closeEntityManager() {

    public void cleanDB() throws Exception {
        DatabaseOperation.CLEAN_INSERT.execute(connection, dataset);

    public void testAUsefulMethod() throws Exception {
        // .... test code


An example structure of the dataset.xml is shown below:

<?xml version='1.0' encoding='UTF-8'?>
    <customer id="1" surname="SURNAME" firstName="FIRSTNAME" middleName="MIDDLENAME" personalAccount="true"/>
    <customer id="2" surname="SURNAME" firstName="FIRSTNAME" personalAccount="true" balance="100000.00/>

One point of note is that when deleting database records using DBUnit the same rules apply as if you were using SQL. You will not be able to delete a record if its primary key is a foreign key on another table. An example in Flat XML for a Customer class that has many Addresses would be:

<?xml version='1.0' encoding='UTF-8'?>

Finally, there are many useful methods on IDataSet and ITable interfaces. An example being to obtain the number of records of a particular table:

int customerRecordCount = dataset.getTable("Customer").getRowCount();


  1. Wouldn't be nice to create the EntityManager in a method annotated with @Before and bind it to a ThreadLocal? By doing this, you will be able to run all your tests in parallel and each thread will have its own EntityManager instance ...

  2. I presume this is all running within junit-runner. How should I get around:
    Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:
    I JBoss (using Arquillian) a datasource will be deployed for you but this does not happen in junit, obviously.


Note: only a member of this blog may post a comment.