I have a life-cycle problem doing some test suite with JUnit.
In order to write handy JPA 2.0 unit tests
As a Java developer
I want to:
- Initialize an EntityManagerFactory instance once before all tests suites. I achieve the object by using the @BeforeClass annotation
- Instantiate an EntityManager instance and start a new transaction before each test case and rollback the started transaction like AOP before/after or around advice
- Be able to make any set up/tear down operations before/after in any derived test suite
I’ve been writing JUnit tests a lot. But in such a case I’ve got problem with the second and third items from the list.
Please take a look of the following test suite examples:
An abstract Test suite:
public abstract class AbstractPersistenceTest {
protected static EntityManagerFactory emf;
protected EntityManager em;
@BeforeClass
public static void setUpClass() {
emf = Persistence.createEntityManagerFactory("test");
}
@Before
public void setUp() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
@After
public void tearDown() {
em.getTransaction().rollback();
em.close();
}
@AfterClass
public static void tearDownClass() {
emf.close();
}
}
A derived test suite:
public class EmployeeJpqlTest extends AbstractPersistenceTest {
private Employee john;
private Employee jack;
@Before
public void setUp() {
john = new Employee("John Doe", 1000);
jack = new Employee("Jack Line", 1010);
em.persist(john);
em.persist(jack);
}
@Test
public void itShouldRetrieveAllEmplloyees() {
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e",
Employee.class);
List<Employee> employees = query.getResultList();
assertArrayEquals(new Employee[] { john, jack }, employees.toArray());
}
@Test
public void itShoulRetrieveAllEmployeeNames() {
TypedQuery<String> query = em.createQuery(
"SELECT e.name FROM Employee e", String.class);
List<String> names = query.getResultList();
assertArrayEquals(new String[] { john.getName(), jack.getName() },
names.toArray());
}
}
Because of unspecified order of JUnit life-cycle annotations the NullPointerException take a place in the setUp() method in the derived class. It’s clear for me.
Is it possible to get the goal without injecting starting/rollbacking transaction code in each setUp()/tearDown() methods of any derived test suite class by hand?
Or, maybe, is there an alternative JUnit mean or test framework that can provide an easy way to express my needs?
Thanks in advance.
How do you like the idea of using Google Guice to inject the Entity Manager and Transactions into your testing methods?
It could simplify a lot of effort in this area.