tags:

views:

72

answers:

2

This is the class I'm trying to test:

@Stateless
public class Finder {
  @PersistenceContext(unitName = "abc")
  EntityManager em;
  public String read(int i) {
    return this.em.find(Employee.class, i).getName();
  }
}

This is the unit test:

public class FinderTest {
  @Test public void testReadingWorks() {
    Finder f = new Finder();
    String name = f.find(1);
    assert(name.length() > 0);
  }
}

The problem is that EntityManager is not injected, and is NULL during testing. What am I doing wrong?

ps. Actually, I don't understand who exactly is going to inject EntityManager. The unit test is started by JUnit, outside of any container... Maybe I have to inject em manually in the test?

+3  A: 

Injection of EntityManagers only works in managed beans, since you are creating the Finder with new no container is involved. You could eithere create the EntityManager yourself using the EntityManagerFactory or use a embeddable Container like OpenEJB in your unit tests.

Jörn Horstmann
@Jorn And where do I get `EntityManagerFactory`?
Vincenzo
@Jorn Besides, this link is more relevant: http://openejb.apache.org/3.0/injection-of-entitymanager-example.html
Vincenzo
@Vincenzo also a good link http://openejb.apache.org/3.0/local-client-injection.html and and example of it here http://s.apache.org/testcase-injection
David Blevins
Works fine with OpenEJB now: http://stackoverflow.com/questions/4042232
Vincenzo
+1  A: 

Actually, I don't understand who exactly is going to inject EntityManager. The unit test is started by JUnit, outside of any container... Maybe I have to inject em manually in the test?

Since your test is running out container, nobody is going to inject anything, you'll have to do it manually. This is IMHO not really a bad thing, and not hard.

Out container

Here is a base class that you could extend to get an EntityManager:

public abstract class JpaBaseRolledBackTestCase {
    protected static EntityManagerFactory emf;
    protected EntityManager em;

    @BeforeClass
    public static void createEntityManagerFactory() {
        emf = Persistence.createEntityManagerFactory("PetstorePu");
    }

    @AfterClass
    public static void closeEntityManagerFactory() {
        emf.close();
    }

    @Before
    public void beginTransaction() {
        em = emf.createEntityManager();
        em.getTransaction().begin();
    }

    @After
    public void rollbackTransaction() {

        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }

        if (em.isOpen()) {
            em.close();
        }
    }

}

In container using the EJBContainer API

Another option would be to run your test in container, using the EJB 3.1 EJBContainer API to start an embedded container. See Arun's TOTD #128: EJBContainer.createEJBContainer: Embedded EJB using GlassFish v3 (you'll need a bit more work to setup the datasource).

In container using Arquillian

Or you could use Arquillian. Have a look at The perfect recipe for testing JPA 2: revisited for some ideas. I tested this approach this morning and find it VERY interesting for real integration tests (but in container tests are typically slower and I won't use them for everything - but I'm starting to love Arquillian).

Pascal Thivent
@Pascal I will try Arquillian (looks interesting so far), and report here...
Vincenzo