Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit life-cycle

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.

like image 988
Dmytro Chyzhykov Avatar asked Oct 08 '22 17:10

Dmytro Chyzhykov


2 Answers

Why don't you call super.setUp() in setUp, super.setUpClass etc? What you are actually doing is overriding the method of the subclass.

like image 20
user3001 Avatar answered Oct 10 '22 09:10

user3001


How do you like the idea of using Google Guice to inject the Entity Manager and Transactions into your testing methods?

import com.google.inject.persist.Transactional;
import javax.persistence.EntityManager; 

public class MyTest {
        @Inject EntityManager em; 

        @Test
        @Transactional 
        public void createNewPerson() {
                em.persist(new Person(...)); 
        } 
}

It could simplify a lot of effort in this area.

like image 177
Edwin Dalorzo Avatar answered Oct 10 '22 08:10

Edwin Dalorzo