Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject PersistenceContext during unit testing?

This is my java class:

public class Finder {
  @PersistenceContext(unitName = "abc")
  EntityManager em;
  public boolean exists(int i) {
    return (this.em.find(Employee.class, i) != null);
  }
}

This is the unit test:

public class FinderTest {
  @Test public void testSimple() {
    Finder f = new Finder();
    assert(f.exists(1) == true);
  }
}

Testing fails with NullPointerException since Finder.em is not injected by anyone. How should I handle this situation properly? Does there any best practice exist?

like image 818
yegor256 Avatar asked Sep 27 '10 20:09

yegor256


People also ask

How do you inject an entity manager?

You can use the @PersistenceContext annotation to inject an EntityManager in an EJB 3.0 client (such as a stateful or stateless session bean, message-driven bean, or servlet). You can use @PersistenceContext attribute unitName to specify a persistence unit by name, as Example 29-13 shows.

What does PersistenceContext annotation do?

The persistence context is the first-level cache where all the entities are fetched from the database or saved to the database. It sits between our application and persistent storage. Persistence context keeps track of any changes made into a managed entity.

How do you write test cases for entity manager?

What you need to insert is a query mock... @Mock private Query query; ... // when createQuery is called, return the mocked query object (instead of null) when(entityManager. createQuery(any(String. class)).

What is PersistenceContext?

A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle are managed.


2 Answers

Without a container like Spring (or something like Unitils - which is Spring based), you will have to inject the entity manager manually. In that case, you could use something like this as base class:

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();
        }
    }
}
like image 131
Pascal Thivent Avatar answered Sep 23 '22 19:09

Pascal Thivent


It depends on what you want to test. When you have complex business logic in your Finder class you may want to mock the EntityManager - using a mocking framework like EasyMock or Mockito - in order to unit test that logic.

Now since that's not the case I suspect you want to test the persistency of the Employee entity (this is often referred to as integration testing). This requires the use of a database. To make testing easy and keep your tests portable you can use an in-memory database like HSQLDB for this purpose. In order to start HSQLDB, create a persistence context and inject this context into your Finder class it's advisable to use an IoC framework like Spring.

There are tons of tutorials on the internet that explain how to use JPA/Spring/HSQLDB. Take a look at this example project: Integration testing with Maven 2, Spring 2.5, JPA, Hibernate, and HSQLDB

like image 32
Richard Kettelerij Avatar answered Sep 26 '22 19:09

Richard Kettelerij