JPA integration tests with Java EE

Last Updated:  February 19, 2020 | Published: October 22, 2018

Writing good unit tests for your central business logic is essential. Both to speed up your development and have confident deployments to production. But there are also parts of your application where plain unit tests with mocking frameworks like Mockito aren't that useful or result in a “mocking-hell”. The interaction of your application with your database is one of these parts where unit tests can't reproduce the real behavior of this external system. For unit testing your business logic, it's totally fine to mock the EntityManager and its result but if you want to write tests for your JPA models, JPQL queries or the general interaction with the database, you should consider writing integration tests. In this blog post, I’ll show a simple way to write JPA integration tests for Java EE applications.

Project setup

To bootstrap the Java EE application I am using my Java EE 8 archetype:

For integration tests, we don’t want to run the application server to improve speed. That's why you have to add the JPA implementation to your project. In addition, I am also using an embedded H2 database to spin off an in-memory database during the tests:

All of the additional dependencies are marked with the scope test , so they won’t be part of your .war  and the application will stay lean.

For connection to the in-memory, you need to add a persistence unit to your persistence.xmlwhich can be stored in /src/main/test/resources/META-INF. As these tests don’t rely on a running application server, the transaction type has to be RESOURCE_LOCAL as we don’t have JTA and have to manually start and commit the transactions:

To demonstrate a quick example I am using drop-and-create as the schema generation action for the integration tests, but you can also use Flyway or Liquibase to apply your database schema for your integration tests.

JPA entity setup and writing efficient tests

A simple JPA entity may look like the following:

For a convenient interaction, I created a JUnit 4 TestRule (kudos to @AdamBien for his test course) which acts as the EntityManager provider for every test. With this rule, you can create the EntityManager from a given unit name. Furthermore, it allows interaction with the EntityManager or the EntityTransaction:

A rudimentary integration test might test the right creation of the primary key with @GeneratedValue. Therefore you need to start the database transaction manually and insert some JPA entities. Afterward querying for all entities in the database should result in a list of entities. Similarly, all should have a primary key in place.

This example is just a simple use case. It demonstrates how to to write integration tests for your database layer. This approach can be also used to test the correct table representation of your JPA entities and more complex queries.

You can find a running example on GitHub.

Further resources on JPA

Find further persistence related tips & tricks here:

Have fun with JPA integration tests for your application,

Philip

>