The Ironism

The Ironism

The lair of Lars J. Nilsson. Contains random musings on beer, writing and this thing we call life.

April 2010


Unit Tests with Guice and Warp Persist


Note: this post is cross-posted on

Yesterday I needed to do some unit testing for a project using Guice and Warp Persist. And one thing that seems to be lacking, or wasn’t to be found be me yesterday, is the kind of unit testing you can do with Spring, where each method is wrapped by a transaction which is rolled back when the method ends.

To simplify, it enables you to do this:

If you assume the “userService” is transactional, we’re on a database that spans multiple methods, and that the user ID must be unique, the above pseudo-code should fail as we’re trying to create two users with the same ID. If, however, there was a transaction wrapping both methods, and that transaction was rolled back, we’d be fine.

So, can you do it with Guice and Warp Persist? Sure you can!

(I’m using TestNG and JPA by the way, but you’ll get the point).

We’ll create a base class that sets up the Guice context as well as handles the transactions for us. Let’s start with creating the methods we need:

We’re using the TestNG “before” and “after” class to setup and tear down JPA. If the test was in a bigger suite you could probably do it around all test classes, but this will do for now. I’m also including a “testModules” method that subclasses should use to make sure their own test classes are setup correctly.

Before we go on, I’ll add some dependencies which will be explained later:

We’ll setup the Guice context and the JPA persistence service in the “setUpJpa” method:

The persistence service will work across UnitOfWork.REQUEST as that’s what we’re emulating here. I’m also matching the transaction for any classes, this enables me to mark an entire class as transactional, as opposed to single methods, which I find handy.

All we need to do to shut down is to close the service, like so:

Now, let’s wrap the methods. Remember our dependency injections earlier? Well, here’s where they come in handy. The WorkManager is used by Warp Persist to manage a session, we can tell it to start and end “work” and this will correspond to an EntityManager bound to the current thread. Let’s start with that:

So before each method we’ll open a new EntityManager which will be closed when the method ends. So far so good. Now, in order to enable a rollback when the method ends we first need to wrap the entire execution in a transaction, which means we need to get hold of the EntityManager. Luckily, Warp Persist has a class called ManagedContext which holds currently bound objects (a bit like a custom scope), in which we’ll find our EntityManager keyed to it’s persistence context, ie. the EntityManagerFactory that created it. Take a look again at the injected dependencies we injected above: As the test only handles one persistence context we can safely let Guice inject a Provider for an EntityManagerFactory for us and assume it is going to be the right one.

Still with me? OK, let’s do it then:

And that’s it! Each test method is now within a transaction that will be rolled back when the method ends. Now all you need to do is to write the actual tests…

The proprietor of this blog. Lunchtime poet, former opera singer, computer programmer. But not always in that order. Ask me again tomorrow.

    Comments 4
    • steven
      Posted on

      steven steven


      tom wilson, is that you?

    • larsan
      Posted on

      larsan larsan


      Er, no?

    • i don’t understand it yet
      Posted on

      i don’t understand it yet i don’t understand it yet


      can you send me one demo to my email [email protected] very much!

    • bloo
      Posted on

      bloo bloo


      Can you describe where (and if) you’re using @Transactional, since you’re defining it as part of your Matcher? I’ve tried several variations of this, and am not able to get anything to rollback (I’m inserting two records via EntityManager.persist(), and want them removed at the end of the test).I’m also assuming: warp-persist-2.0-20090214.jar, guice-2.0.jar ? What database and which version are you using?Thanks.