2012-05-28 74 views
5

Tengo un problema de ciclo de vida haciendo un banco de pruebas con JUnit.JUnit ciclo de vida

el fin de escribir a mano unidad de JPA 2.0 pone a prueba Como desarrollador de Java Quiero:

  • inicializar una instancia EntityManagerFactory una vez antes de todas las suites de pruebas. Me lograr el objeto mediante el uso de la anotación @BeforeClass
  • se crea una instancia de EntityManager y comenzar una nueva transacción antes de cada caso de prueba y deshacer la transacción iniciada como AOP antes/después o alrededor consejos
  • será capaz de hacer cualquier configurar/derribar operaciones antes/después en cualquier suite de pruebas derivadas

He estado escribiendo pruebas JUnit mucho. Pero en tal caso tengo un problema con los artículos segundo y tercero de la lista.

favor, eche un vistazo de los siguientes ejemplos de pruebas que:

Un conjunto de pruebas genéricas:

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(); 
    } 

} 

Un conjunto de pruebas derivadas:

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()); 
    } 

} 

Debido a no especificada orden de las anotaciones de ciclo de vida JUnit la NullPointerException toma un lugar en th e método setUp() en la clase derivada. Está claro para mí.

¿Es posible obtener el objetivo sin inyectar el código de transacción inicial/rollbacking en cada método setUp()/tearDown() de cualquier clase de conjunto de pruebas derivadas a mano? O, tal vez, ¿existe un marco de prueba o prueba alternativa de JUnit que pueda proporcionar una manera fácil de expresar mis necesidades?

Gracias de antemano.

Respuesta

2

¿Qué le parece la idea de usar Google Guice para inyectar el gestor de entidades y transacciones en sus métodos de prueba?

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(...)); 
     } 
} 

Podría simplificar un montón de esfuerzo en esta área.

+0

Sí, es una buena idea. Como Google Guice es un Lean IoC, se puede usar sin impacto del código. –

1

¿Por qué no llama al super.setUp() en setUp, super.setUpClass etc.? Lo que en realidad está haciendo es anular el método de la subclase.

+0

En realidad lo estaba haciendo de esa manera y, como resultado, el método padre 'setUp()' fue invocado dos veces seguidas durante la prueba, una vez directamente desde mi código y la segunda vez por JUnit con respecto al ciclo de vida de JUnit. –

1

Considere usar Spring para manejar la creación de instancias únicas de un administrador de entidades no estáticas y la reversión de transacciones. Incluso si no está usando Spring en su aplicación, puede beneficiarse de usarlo solo en sus pruebas. Ver la sección 9.3 de http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/testing.html para más detalles.

+0

Sí, estoy completamente de acuerdo con usted. Es una gran alternativa útil. Ese proyecto en particular es tan pequeño y simple, así que evito usar Spring, con la comprensión de lo que rechazo. Gracias. –

Cuestiones relacionadas