Running JPA tests

I’ve been trying to get to a place where I can achieve all the following goals:

  • Have my domain entities be pure JPA @Entity instances.
  • Run JUnit tests against those entities using the “big three” JPA providers (Hibernate, EclipseLink and OpenJPA).
  • Set up and tear down an in-memory database in a predictable way
  • Run the whole mess with Maven without any special JUnit code

I’m going to talk a bit about the second and last points.

To run a JPA test, you’re going to need an EntityManager.  And to get an EntityManager in a non-EJB environment, you’re going to need a JPA provider on the classpath.

You basically have three JPA providers to choose from: EclipseLink, Hibernate and OpenJPA.  These are the ones that are in wide use today, so they’re the ones I’m going to focus on.  You want to be able to back up any claim you make that your JPA entities will run under these big three providers, so to do that you need to make sure you’re unit testing them.

We’d like our tests to exercise our entities using each of these in turn.  Further, we’d like our tests to be run in their own process, with an environment as similar to the end environment as possible, while not including any extra crap.

So to begin with, we’re going to have to get Surefire (Maven’s test runner plugin) to run three times in a row, with a different JPA provider each time.

The first time I attempted this, I thought I’d use the @Parameterized annotation that comes with JUnit.  This annotation lets you set up a test class so that JUnit will run it multiple times with different input data.  I had set it up so that the input data was a String that identified the persistence unit and the JPA provider.  This worked fine, but the multiple times your test runs are not each in their own process.  As a result, you end up having all three JPA providers on the classpath at the same time, and various problems can result.  The whole solution was rather brittle.

Instead, we want to have Maven control the test execution, not some looping construct inside JUnit.

The first insight I had was that you can set up a plugin in a pom.xml file to run several times in a row.  This is, of course, blindingly obvious once you see it (if you’re used to staring at Maven’s XML soup), but it took me a while to realize it’s possible.

Here, for example, is a way to configure the maven-surefire-plugin to run three times (with no other configuration):

<build>
  <plugins>
  <plugin>

    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.7.2</version>
    <configuration>
      <skip>true</skip>
    </configuration>
    <executions>
      <execution>
        <id>First Surefire run</id>
        <goals>
          <goal>test</goal>
        </goals>
        <phase>test</phase>
        <configuration>
          <skip>false</skip>
        </configuration>
      </execution>
      <execution>
        <id>Second Surefire run</id>
        <goals>
          <goal>test</goal>
        </goals>
        <phase>test</phase>
        <configuration>
          <skip>false</skip>
        </configuration>
      </execution>
      <execution>
        <id>Third Surefire run</id>
        <goals>
          <goal>test</goal>
        </goals>
        <phase>test</phase>
        <configuration>
          <skip>false</skip>
        </configuration>
      </execution>
    </executions>
  </plugin>
  <!– other plugins here –>
  </plugins>
<!– other build info –>
</build>

Run mvn test and you’ll see Surefire run three times.  (There’s actually a MUCH shorter way to accomplish this trivial three-run configuration, but it won’t aid our ultimate cause, so I’ve opted to stay verbose here.)

We’ve told Surefire that by default it should skip running.  Then we’ve provided it with three executions (identified with <id> elements so we can tell them apart).  Each execution is structured to run the test goal during the test phase, and tells Surefire that it should not skip.

It’s important to note that the <configuration> element, when contained in an <execution>, applies only to that <execution>, and overrides any related settings in the default <configuration> (housed immediately under the <plugin> element), if there is one.  We’re going to make heavy, heavy use of this fact.

So hopefully you can start to see that the looping of the test cases can be controlled by Maven.  We know that we’re going to run Surefire three times–one time for each JPA provider–and now we want to make sure that each iteration is in its own process.  Let’s enhance the default configuration of this skeletal block a bit:

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <skip>true</skip>
    <forkMode>always</forkMode>
    <useFile>false</useFile>
  </configuration>

We’ve told Surefire to always fork, and (purely for convenience) told it to spit any errors to the screen, not to a separate file.  So this solves the test looping problem.  We have our skeleton.  On to part 2.

Advertisements

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