Unit test JPA Entities with in-memory database

HibernateStill about Hibernate, I have several JPA Entities grouped in a Persistence Unit that I need to test. So here is another quick and dirty howto titled “Unit test JPA Entities with in-memory database”.

Here I assume you already have written your entities java classes with correct annotations.

As I’m working with embedded Derby for a year, I first tried with it but procton (thank you procton) pointed me to another lightweight RDBMS.

So, in this how-to we will set up a unit-tests dedicated persistence unit and use HSQLDB as in-memory database for unit tests.

UPDATE: now that Apache Derby provide an in memory backend, I implemented the very same thing with it in a new post : Unit test JPA Entities with in-memory Derby/JavaDB


Dependencies

I won’t mess with classpath issues here because I’m extensively using maven and … I don’t mess with simple classpath issues anymore :) <subliminal>use maven, use maven, use maven, it’s a good piece of software</subliminal>

Here are the dependencies I added to my project with the “test” scope :

<dependency>
	<groupId>org.hibernate</groupId>
	<artifactId>hibernate-entitymanager</artifactId>
	<version>3.3.1.ga</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>hsqldb</groupId>
	<artifactId>hsqldb</artifactId>
	<version>1.8.0.7</version>
	<scope>test</scope>
</dependency>

I needed the hibernate-entitymanager as it’s a project with only entity classes in it.

Persistence Unit

Here the interesting snippet of my META-INF/persistence.xml file :

<persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>myapp.model.entities.Group</class>
    <class>myapp.model.entities.User</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:unit-testing-jpa"/>
        <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        <property name="hibernate.connection.username" value="sa"/>
        <property name="hibernate.connection.password" value=""/>
    </properties>
</persistence-unit>

It’s only a snippet because I have several persistance-unit nodes, one for production, one for development, one for unit testing.

The unit test

I’m still using JUnit 3 but if you’re using the 4th version, you won’t be lost. Here is a simple complete test case :

 public class PersistenceUnitTest extends TestCase {

    private static Logger logger = Logger.getLogger(PersistenceUnitTest.class.getName());

    private EntityManagerFactory emFactory;

    private EntityManager em;

    private Connection connection;

    public PersistenceUnitTest(String testName) {
        super(testName);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        try {
            logger.info("Starting in-memory HSQL database for unit tests");
            Class.forName("org.hsqldb.jdbcDriver");
            connection = DriverManager.getConnection("jdbc:hsqldb:mem:unit-testing-jpa", "sa", "");
        } catch (Exception ex) {
            ex.printStackTrace();
            fail("Exception during HSQL database startup.");
        }
        try {
            logger.info("Building JPA EntityManager for unit tests");
            emFactory = Persistence.createEntityManagerFactory("testPU");
            em = emFactory.createEntityManager();
        } catch (Exception ex) {
            ex.printStackTrace();
            fail("Exception during JPA EntityManager instanciation.");
        }
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        logger.info("Shuting down Hibernate JPA layer.");
        if (em != null) {
            em.close();
        }
        if (emFactory != null) {
            emFactory.close();
        }
        logger.info("Stopping in-memory HSQL database.");
        try {
            connection.createStatement().execute("SHUTDOWN");
        } catch (Exception ex) {}
    }

    public void testPersistence() {
        try {

            em.getTransaction().begin();

            User u = new User();
            u.setEmail("eskatos@yopmail.com");
            u.setFirstName("eskatos");
            u.setLastName("YOP");
            u.setOrganisation("Tagada");

            em.persist(u);
            assertTrue(em.contains(u));

            Group g = new Group();
            g1.addUser(u);

            em.persist(g);
            assertTrue(em.contains(g));

            g.removeUser(u);
            em.remove(u);
            em.merge(g);
            assertFalse(em.contains(u));

            em.getTransaction().commit();

        } catch (Exception ex) {
            em.getTransaction().rollback();
            ex.printStackTrace();
            fail("Exception during testPersistence");
        }
    }
}

Et voila !

Advertisements

16 thoughts on “Unit test JPA Entities with in-memory database

  1. Hi,

    thanks for you article. I am doing the same type of testing but can’t figure out how to do testing and deployment using a single persistence.xml. The problem is when I deploy into jboss it doesn’t like the unit testing persitence context being defined because it’s resource-local. I am interested to know if you have faced similar issue and how you solved the pb.

    thanks
    andre

  2. Hi Andre,

    I do not have this issue. Using Hibernate in GlassFish here.
    Now I’m using separate persistence.xml files and my build tool (maven) allows me to change the persistence.xml file used during unit tests.

    It’s no solution but I hope this helps.

    Paul

  3. Hey Paul,

    Thanks for the reply. I guess using the build tool to select the appropriate file is really the way to go.

    In the mean time i have noticed that Jboss complains about seeing a “resouce-local” persistence context but deploys everything ok. So for the moment i am living with the error and will get to modifying my ant script shortly.

    thanks
    andre

  4. Tried this out just now. Using Maven, too and practically followed your example to the letter but am getting “java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/Persistence”.

    Any ideas? Do I have to add the Glassfish runtime libraries (or in my case, JBoss) to the classpath via Maven dependencies, too (not covered in your post)?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s