Anotaciones JUnit en Java
Anotaciones principales de JUnit 5: @Test, @BeforeEach, @AfterEach, @BeforeAll, @AfterAll y @Disabled.
JUnit 5 es el framework de pruebas estándar de facto para Java, y casi todo lo que le indicas ocurre a través de anotaciones. No escribes un método main ni llamas a métodos tú mismo; decorás métodos ordinarios con anotaciones como @Test, @BeforeEach y @AfterAll, y el motor de JUnit los descubre por reflexión y los ejecuta en el orden correcto. Este capítulo cubre las anotaciones principales del ciclo de vida — qué significa cada una, cuándo se dispara y cómo se combinan para dar a cada prueba un entorno limpio y aislado.
Si eres nuevo en el framework, comienza con la introducción a JUnit; para los ayudantes de aserciones que invocan estas pruebas, consulta aserciones de JUnit. Las anotaciones en sí son una característica general de Java tratada en anotaciones de Java.
Las anotaciones viven en org.junit.jupiter.api
La API de JUnit 5 es el módulo Jupiter. Las anotaciones que usas a diario provienen de un solo paquete:
| Anotación | Se aplica a | Se ejecuta |
|---|---|---|
@Test | un método | una vez por método de prueba |
@BeforeEach | un método | antes de cada @Test |
@AfterEach | un método | después de cada @Test |
@BeforeAll | un método static | una vez, antes de cualquier prueba en la clase |
@AfterAll | un método static | una vez, después de todas las pruebas en la clase |
@Disabled | un método o clase | nunca (se omite y se notifica) |
@DisplayName | un método o clase | establece un nombre legible en los informes |
Un método marcado con @Test no necesita el modificador public en JUnit 5 (el acceso de paquete es válido) y debe retornar void.
@Test: la unidad de trabajo
Un método de prueba afirma algo usando los ayudantes estáticos de org.junit.jupiter.api.Assertions. Si una aserción falla, lanza una excepción y el motor registra esa prueba como fallida sin detener las demás.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void addsTwoNumbers() {
Calculator calc = new Calculator();
assertEquals(5, calc.add(2, 3));
}
@Test
void throwsOnDivideByZero() {
Calculator calc = new Calculator();
assertThrows(ArithmeticException.class, () -> calc.divide(1, 0));
}
}Cada @Test se ejecuta en una instancia nueva de la clase de prueba — JUnit construye un nuevo objeto por prueba de forma predeterminada, por lo que los campos establecidos en una prueba no pueden filtrarse a otra.
@BeforeEach y @AfterEach: entornos por prueba
La configuración que necesita cada prueba va en un método @BeforeEach; la limpieza va en @AfterEach. Encuadran cada @Test, proporcionando a cada prueba un punto de partida idéntico.
import org.junit.jupiter.api.*;
class OrderServiceTest {
private OrderService service;
@BeforeEach
void setUp() {
service = new OrderService(new InMemoryRepo()); // fresh state per test
}
@AfterEach
void tearDown() {
service.close(); // runs even if the test threw
}
@Test
void placesOrder() {
assertTrue(service.place("SKU-1", 2));
}
}@AfterEach se ejecuta incluso cuando la prueba falla, lo que lo convierte en el lugar correcto para liberar recursos que abriste en @BeforeEach.
@BeforeAll y @AfterAll: una vez por clase
Cuando la configuración es costosa y se puede compartir — un contenedor de base de datos, un servidor embebido iniciado — usa @BeforeAll para hacerlo una vez y @AfterAll para desmontarlo una vez. Como se ejecutan antes de que exista alguna instancia, deben ser static.
import org.junit.jupiter.api.*;
class RepositoryTest {
static Database db;
@BeforeAll
static void startDatabase() {
db = Database.start(); // runs once, before everything
}
@AfterAll
static void stopDatabase() {
db.stop(); // runs once, after everything
}
@Test
void savesRow() {
assertEquals(1, db.insert("hello"));
}
}El orden completo del ciclo de vida para una clase con dos pruebas es: @BeforeAll → (@BeforeEach → @Test → @AfterEach) → (@BeforeEach → @Test → @AfterEach) → @AfterAll. El capítulo ciclo de vida de JUnit detalla este orden, incluyendo cómo interactúa con la creación de instancias.
@Disabled: omitir sin eliminar
@Disabled desactiva una prueba (o una clase entera). El motor la reporta como omitida en lugar de aprobada o fallida, por lo que permanece visible. Siempre incluye una razón.
@Test
@Disabled("flaky until the rate-limiter fix lands — see JIRA-1234")
void callsExternalApi() {
// not executed
}Un ejemplo completo: un mini motor de pruebas
No hay un jar de JUnit en este ejecutor, así que el programa a continuación construye un pequeño motor propio con exactamente la misma forma que JUnit. Declara anotaciones marcadoras (@BeforeAll, @BeforeEach, @Test, @AfterEach, @AfterAll, @Disabled), define una pequeña clase de prueba anotada y luego usa reflexión — precisamente lo que hace el motor de JUnit internamente — para descubrir y ejecutar los métodos en orden de ciclo de vida e imprimir un resumen de aprobado/fallido/omitido.
Lo que se puede observar en la ejecución:
@BeforeAllse imprime exactamente una vez al inicio y@AfterAllexactamente una vez al final — la configuración y el desmontaje a nivel de clase encuadran toda la ejecución, razón por la que JUnit requiere que seanstatic.- Cada
@Testejecutado está precedido por una línea@BeforeEachy seguido por una línea@AfterEach, por lo que cada prueba se ejecutó contra un entorno recién preparado y se limpió al terminar — el encuadre por prueba que mantiene las pruebas independientes. - El método
flakyllevaba@Disabled, por lo que imprimió(skipped via @Disabled)y su cuerpo nunca se ejecutó; la aserción fallida dentro de él nunca se alcanzó, que es el objetivo de deshabilitar en lugar de eliminar. - El bucle de descubrimiento solo actúa sobre métodos donde
isAnnotationPresent(Test.class)es verdadero — las anotaciones son solo metadatos, y es el motor el que las lee mediante reflexión para convertirlas en comportamiento, exactamente como funciona JUnit real. - La línea final reporta
2 passed, 0 failed, 1 skipped: dos pruebas reales pasaron, ninguna falló, y la deshabilitada se contó como omitida en lugar de ignorarse silenciosamente — la misma contabilidad de aprobado/fallido/omitido que te da un informe de JUnit.