Unit Testing EJBs

March 27th, 2007

As we’ve done more and more EJB development, we’ve had to think pretty hard about how to unit test our beans. We’ve tried a couple of different approaches (including not testing, which I don’t recommend ;), but weren’t ever just real comfortable with the results. I’m pretty happy with the method we’re using now, and it’s so simple, I’m a bit embarrassed that we didn’t think of it earlier.

One of our earliest attempts used JBoss’ embeddable container, which we eventually discarded for a couple of reasons. It was really heavy in terms of configuration and startup time, and, as hard as I’m sure the JBoss team is working on AS 5 in terms of EE 5 compliance, the embeddable container is still using an old version of the spec, which meant we had to change the way we handled resource look ups, which we didn’t like. We’ve also tried using mock objects, but, for the most part, we found that to be overkill. What we ended up with is pretty light and simple.

To make things work, we had to change the way we setup our EJBs. Since the beginning our EE 5 development, we’ve been using field injection:

which we have changed to using property injection:

Our general approach has been to avoid making changes to production code for the purpose of testing, but, after talking things over with a friend from our local JUG, I felt the change was not only appropriate, but a good general philosophy change. What Rod explained to me is that, by using property injection, we make our beans reusable across integration technologies. If, for example, we ever wanted to use this class with Guice or Spring, we’d be out of luck using field injection, as they don’t support that. They do, though, support property injection, so using that makes sense in terms of portability.

With that change made, our unit tests became a lot easier to write. Our applications are all multi-tiered, with JSF handling the view, and service and DAO layers that are either Faces-managed or container-managed and Session Beans, depending on the need for remote access. For the purposes of our discussion here, we’ll start with the data layer. Let’s say we have this simple DAO:

This is a very simple DAO, and there is a lot intentionally left out, but it demonstrates a simple DAO using JPA. So how do we test that? How do we create the EntityManager, for example? Here’s how the unit test might look using JUnit 4 and DBUnit:

The unit test starts by declaring some static resources: the DAO implementation, an EntityManagerFactory, and an EntityManager. In the @BeforeClass, we ask the EMF for the EntityManager, then pass that to a DBUnit helper class, then set the EM on the DAO (you should see now where the property injection comes in handy). The @Before method simply loads our test data before each test. One could just as easily have each unit test rollback at the end, but we chose to reload our small test dataset before each run. The unit test itself is fairly straightforward, except that we are explicitly handling transactions to mimic the container-managed transaction handling we get for free in production.

The persistence context is defined like this:

Here is the code for the DBUnitHelper class. Note that this is still experimental, but I’ve used it on three projects now with good success, but it does abuse the JPA API by talking to the TopLink objects directly, so it is definitely not portable. You have been warned. :)

Testing our service is fairly similar, needing just a bit more setup:

This test is very similar to the DAO test, including transaction management, but we call the service instead of the DAO. I also chose to create a “real” instance of the DAO as opposed to mocking one up, since the resource was local to the project. That makes the test more of an integration test in some ways, but we’re OK with that.

For external resources, we’re tempted to use mock objects, but another sharp OKC JUG regular, Dave Nicolette, suggests that that might be overkill. Anything we might inject we will have an interface for, so he suggests just writing a stubbed implementation of the interface and injecting that, making our “stub” behave the way our test expects, which would allow us to focus on testing the client and not the “remote” object. That’s an interesting approach. I have not been able to test that yet, but I certainly will when the need arises.

That about sums it up. All that’s left to test is the JSF layer, for which we don’t have a solution with which I’m all that comfortable. Once we nail something down, I’ll be sure to write it up here. :)

So, how is everyone else testing EJBs? Comments, suggestions, corrections, etc. are, of course, welcome!

Popularity: 22% [?]

7 Comments

  1. vicnov says

    Jason, thanks for this idea of testing EJBs!
    Some time ago we worked at a project with EJB 3.0 beans, and our unit-tests worked with EJBs deployed to app server. This worked well but required much time for deployment…
    After that I worked (and working now) with Spring - I was surprised how it is simple and fast to run unit-tests in Spring. No deployment, but your test class should be inherited from some Spring’s class which prepares environment, manage transactions etc.
    Now, after your article I see that I can do almost the same with session beans in EJB 3.0.

    I have just 2 ideas to propose:
    1. You could create a base (parent) class which manages transactions, creates EntityManager, etc. All your test classes could inherit it.
    2. If necessary, you can deal even with field-level injection using Java Reflection
    3. You could use Spring itself for unit-testing. But this way you may end up by asking “Do I really need Java EE container or I could use Spring with any Servlet container?” :-)

    March 30th, 2007 | #

  2. jason says

    vicnov, thanks for the feedback. A base class for txn handling, or even use of @Before methods would likely simplify txn handling a bit, but also make things a little less flexible — just depends on your intended usage, I guess, but a good point either way. As far as Spring goes, we’ve already settled that discussion. All we were using Spring for was DI, which we get for free with EJB3 with less configuration and one less library (and its 573 dependecies). While I think Spring is great, and we still use things like the JdbcTemplate, EJB3 made more sense for us given our environment (GlassFish, JSF 1.2, etc). :)

    April 2nd, 2007 | #

  3. Szymono says

    Hi,

    Could you tell me is above method better than ejb3unit method (http://ejb3unit.sourceforge.net)?

    Best Regards,
    Szymono

    April 27th, 2007 | #

  4. jason says

    Szymono,

    I’m not sure it’s “better,” really, I just like the way it works better, if that makes sense. We tried ejb3unit and had some issues with it. To be honest, that was so long ago, I can’t remember off the top of my head. I seem to remember thinking that it was awfully heavy. Having said all of that, if ejb3unit works for you and you like it, there’s no reason to switch that I can see.

    April 27th, 2007 | #

  5. JohnBat26 says

    Hello all !
    This method for testing seem good, but this while we has small model.
    How I must test Session Beans, if it dependence from 5-level graph Entities ?
    I must very long tediously work istead container, executing DI myself. :(
    Or one session bean depend from 5 session beans ?

    May 5th, 2007 | #

  6. loester says

    Jason, thanks for sharing your gem.

    To the JBoss/Hibernate folks: you can easily make your own DBUnitHelper using the following information:
    http://www.censnet.it/articles/cap03.htm

    May 7th, 2007 | #

  7. Gonzalo says

    Hello everyone, I am trying to find any examples of EJB3Unit usage, but i can’t. Does anyone knows any place where i can get some? Because the documentation about using rc2 is not in the project site :(

    Thanks

    Gonzalo

    June 28th, 2007 | #

Sorry, the comment form is closed at this time.

With many thanks to Kaushal Sheth
`