views:

75

answers:

3

I'm working on a Java EE 6 application. When I started out, I was writing tests for my EJB classes by manually instantiating the EJB, then manually adding the members that normally get provided by dependency injection. As the application gets more complicated, I find that this approach just doesn't cut it. So I'd like to be able to start my own EJB container in the test framework, so it can manage my beans. What's the best way to approach this? I've heard of javax.ejb.embeddable.EJBContainer, are there other options?

(I'm using Glassfish 3, and building with Maven, if that makes any difference.)

A: 

I'm not entirely sure if that helps your case, but have a look at Smokestack. I personally don't work in the EE space (outside of the Servlet spec) but I did see a presentation on this at one point and looks like it can do what you need.

whaley
+1  A: 

What exactly are you testing? Logic? Configuration? Do you NEED to test the EJB classes directly? Would it suffice for your tests to behave as an EJB client against a running container? (Remember there's no rule that says automated unit tests can't require a running system-under-test.)

If it's business logic you need to test, move that code into POJOs and test normally; you wouldn't need to then test the POJOs running in a container, as the container shouldn't affect the business logic.

In a related situation, I have never directly JUnit-tested a servlet class or a Struts controller class. I definitely test the POJOs those depend on, and I test the end application (running in a servlet container, tested with HtmlUnit), assuming that if the end app works, then the plumbing works too.

Rodney Gitzel
Obviously, testing POJOs is easier. But I can't move all the logic out of my EJBs and into free-standing classes - if I could do that, I wouldn't be using EJBs in the first place. Acting as an EJB client against a running container is a good description of what I'm trying to do, I'm just trying to figure out the best way to achieve this.
Mike Baranczak
I think you were right about testing the deployed application. I tried to get EJBContainer working for me (using glassfish-embedded as the implementation), jumped through a lot of hoops to make persistence work, then finally quit when I realized that an EJB timer service (which my app depends on in several places) wasn't provided. I realized that even if I manage to put together some sort of engine to run my EJBs, it would never replicate ALL the conditions inside a real container, so it would be a useless test.
Mike Baranczak
`Remember there's no rule that says automated unit tests can't require a running system-under-test` Well, actually, there are rules and such tests aren't unit tests, by definition :)
Pascal Thivent
Pascal, true to a point -- but where's the fun in following rules? :p *My* definition of "unit" testing is more along the lines of "any testing done by the developer of some code to determine to THEIR satisfaction the code works as THEY understand it should." Sometimes that means testing one method, sometimes it's testing the whole app. Sometimes it involves real third-party integration, sometimes stubs and mocks.
Rodney Gitzel
Pascal is right. "Unit test" has a specific definition: it's the testing of small parts of the code in isolation. When you test the whole thing, it's called "integration testing".
Mike Baranczak
"Small" is such a relative term: pedantically, "unit testing" should only test individual classes with no dependencies. If I am testing class A which needs to have a class B injected before testing... am I now integration testing? *shrug* Probably best to just say "testing"?
Rodney Gitzel
+1  A: 

I've heard of javax.ejb.embeddable.EJBContainer, are there other options?

The EJBContainer API is an option. The other one would be to use Arquillian (and SchrinkWrap).

Some more links:

Pascal Thivent
Arquillian looks pretty nice, but it doesn't seem to provide an EJB timer service, so in my case, it would have limited utility. Also see my response to Rodney.
Mike Baranczak
@Mike Are you *sure* glassfish embedded doesn't provide an EJB timer service? AFAIK, glassfish embedded is a "real" container.
Pascal Thivent
It seems like it SHOULD be available, but when I was using it through the EJBContainer API, I got an error message about the timer service being unavailable. I couldn't find any relevant documentation, except one brief forum posting saying that glassfish-embedded doesn't have a timer service. There might be a way to make it work, but I don't have time to figure it out, and I can get what I need in other ways.
Mike Baranczak