Una prueba unitaria comprueba una unidad de código — normalmente un método o una clase — aislada de sus dependencias. JUnit 5 es el framework estándar en Java para escribirlas y Mockito permite simular las dependencias.
Las pruebas siguen el patrón AAA (*Arrange-Act-Assert*): preparar, actuar, comprobar.
@Test
void calculatesTotalWithDiscount() {
// Arrange
PriceCalculator calculator = new PriceCalculator();
// Act
Money total = calculator.totalWithDiscount(100, 20);
// Assert
assertEquals(80, total.amount());
}
| Anotación | Función |
|---|---|
@Test | Marca un método como prueba |
@DisplayName | Descripción legible de la prueba |
@BeforeEach | Se ejecuta antes de cada prueba |
@AfterEach | Se ejecuta después de cada prueba |
@Disabled | Desactiva temporalmente la prueba |
Con Maven, mvn test compila y ejecuta todas las pruebas.
Las aserciones comparan el resultado esperado con el real. Si fallan, la prueba falla y muestra la diferencia.
assertEquals(expected, actual); assertTrue(condition); assertFalse(condition); assertNull(value); assertThrows(IllegalArgumentException.class, () -> calculator.totalWithDiscount(-1, 0));
class CalculatorTest {
private PriceCalculator calculator;
@BeforeEach
void setUp() {
calculator = new PriceCalculator();
}
@Test
void calculatesTotal() { /* ... */ }
}
@BeforeEach crea un estado limpio para cada prueba: ninguna depende de la anterior.
Una unidad aislada no puede tocar la base de datos ni la red. Un doble de prueba sustituye una dependencia por una simulación controlada. Con Mockito se declara el mock, se configura su comportamiento y se comprueba su uso.
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
OrderRepository repository;
@InjectMocks
OrderService service;
@Test
void returnsOrderWhenFound() {
Order stored = new Order(42L);
when(repository.findById(42L)).thenReturn(Optional.of(stored));
Order result = service.findById(42L);
assertEquals(stored, result);
verify(repository).findById(42L);
}
}
| Herramienta | Función |
|---|---|
@Mock | Crea el doble |
when(…).thenReturn(…), given(…) | Define qué devuelve el doble |
@InjectMocks | Inyecta los dobles en el objeto probado |
verify(…) | Comprueba que se llamó al doble como se esperaba |
En un monolito por capas, las pruebas unitarias también cubren la colaboración entre capas, simulando la capa inferior. Por ejemplo, probar el controller con el service mockeado comprueba que el controlador delega y traduce correctamente, sin ejecutar la lógica real:
@ExtendWith(MockitoExtension.class)
class BookControllerTest {
@Mock
BookService service;
@Test
void mapsServiceResultToResponse() {
when(service.findById(1L)).thenReturn(new Book(1L, "Clean Code"));
BookResponse response = new BookController(service).get(1L);
assertEquals("Clean Code", response.title());
}
}
Así se comprueba el contrato entre capas: qué se pide y qué se devuelve, no la implementación de cada capa.