Cómo usar BeforeEach, AfterEach, BeforeAll y AfterAll en JUnit 5

Con las anotaciones BeforeEach, AfterEach, BeforeAll y AfterAll podemos marcar métodos para que JUnit los invoque antes y después, tanto de ejecutar cada prueba unitaria, como de ejecutar toda una clase llena de pruebas unitarias. Estos hooks nos permiten crear clases de prueba más compactas evitando repetir código de construcción o destrucción que forme parte de todos los tests de un archivo.

En el desarrollo de pruebas unitarias con JUnit 5, es fundamental contar con mecanismos que nos permitan ejecutar código antes y después de cada test, así como al inicio y al final de toda una suite de pruebas. Esto no solo nos ayuda a evitar la duplicación de código, sino que también facilita la gestión eficiente de recursos y la organización de nuestras pruebas.

Para ilustrar esto, podemos imaginar una clase de pruebas llamada LifecycleTest, donde los métodos anotados con @Test representan los tests individuales. Aunque estos métodos pueden contener código propio, JUnit nos ofrece anotaciones específicas para ejecutar código adicional en momentos clave del ciclo de vida de las pruebas.

La anotación @BeforeEach nos permite definir un método que se ejecutará antes de cada test. Esto es especialmente útil para inicializar variables o preparar el estado necesario para cada prueba sin repetir código en cada método de test. Por ejemplo, si en varios tests creamos objetos similares, podemos centralizar esa creación en un método anotado con @BeforeEach:

@BeforeEach
void setup() {
    p1 = new Producto("Producto1", 10);
    p2 = new Producto("Producto2", 20);
    pedido = new Pedido();
}

De esta forma, antes de cada test, los objetos p1, p2 y pedido estarán listos para usarse, evitando la duplicación y asegurando que cada prueba parte de un estado limpio.

De manera complementaria, @AfterEach nos permite ejecutar código justo después de cada test. Esto es útil para liberar recursos, limpiar estados o realizar cualquier acción necesaria para dejar el entorno preparado para la siguiente prueba. Por ejemplo, si trabajamos con listas compartidas o conexiones externas, podemos vaciar o cerrar esos recursos en un método anotado con @AfterEach:

@AfterEach
void cleanup() {
    pedido.vaciar();
}

Además de estas anotaciones que actúan antes y después de cada test, JUnit 5 ofrece @BeforeAll y @AfterAll, que se ejecutan una única vez antes de que comience la ejecución de todos los tests de una clase y después de que todos hayan terminado, respectivamente. Estos métodos deben ser estáticos y son ideales para inicializar recursos costosos o globales, como conexiones a bases de datos o configuraciones que no cambian entre tests.

Un ejemplo de uso sería:

@BeforeAll
static void initAll() {
    conexion = new ConexionBaseDatos();
    conexion.abrir();
}

@AfterAll
static void tearDownAll() {
    conexion.cerrar();
}

Sin embargo, debemos tener cuidado al usar variables estáticas compartidas entre tests, ya que el estado puede persistir entre pruebas y causar resultados inesperados. Por ejemplo, si un objeto pedido es estático y se modifica en un test, el siguiente test podría encontrarlo en un estado alterado, lo que puede provocar fallos difíciles de detectar.

Para mitigar esto, podemos combinar @AfterEach para limpiar el estado después de cada test, asegurando que cada prueba comience con un entorno consistente:

@AfterEach
void limpiar() {
    pedido.vaciar();
}

En general, es recomendable evitar el uso excesivo de variables estáticas compartidas y preferir la inicialización en @BeforeEach para mantener la independencia de los tests y facilitar su mantenimiento.

Con estas anotaciones y prácticas, podemos mejorar significativamente la organización y limpieza de nuestras pruebas unitarias, evitando duplicaciones y gestionando recursos de forma eficiente. Así, nuestras pruebas serán más robustas, claras y fáciles de mantener.

Lista de reproducción
  1. 1
    ¿Qué es una prueba unitaria? ¿Me vale con crear un main?
    7 minutos
  2. 2
    Cómo crear tests unitarios con JUnit 5
    17 minutos
  3. 3
    Cómo usar BeforeEach, AfterEach, BeforeAll y AfterAll en JUnit 5
    11 minutos
  4. 4
    Cómo cambiar el orden de los tests de JUnit 5 (aunque no deberías)
    8 minutos
  5. 5
    Cómo aprovechar la clase Assertions de JUnit 5
    8 minutos
  6. 6
    Cómo ejecutar tests condicionalmente en JUnit 5
    7 minutos
  7. 7
    Cómo hacer tests de excepciones en JUnit 5 con assertThrows
    5 minutos
  8. 8
    Cómo crear Nested tests en JUnit 5 (un test dentro de otro)
    5 minutos
  9. 9
    Cómo configurar y crear tests de JUnit 5 en NetBeans
    6 minutos
  10. 10
    Cómo configurar y crear tests de JUnit 5 en Eclipse
    5 minutos
  11. 11
    Cómo configurar y crear tests de JUnit 5 en IntelliJ IDEA
    4 minutos