Glosario · Fundamentos de testing
Prueba unitaria (unit test)
En inglés: Unit test
También llamado: unit tests, pruebas unitarias, test unitario, tests unitarios
Definición
Test automatizado que comprueba una pequeña pieza de código, como una función o una clase, de forma aislada de bases de datos, redes y otros servicios.
Una prueba unitaria (unit test) ejercita una pequeña unidad de código, normalmente una función, un método o una clase, y comprueba su salida o su comportamiento para unas entradas dadas. Se ejecuta en memoria, sin bases de datos reales, llamadas HTTP ni sistemas de archivos, así que tarda milisegundos y falla por un único motivo. Los tests unitarios forman la base de la pirámide de pruebas y suelen escribirlos los desarrolladores junto con el código.
Ejemplo (JUnit 5, Java 21)
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class DiscountCalculatorTest {
private final DiscountCalculator calculator = new DiscountCalculator();
@ParameterizedTest
@CsvSource({ "99.99, 0.00", "100.00, 10.00", "250.00, 25.00" })
void appliesTenPercentFromOneHundred(double total, double expected) {
assertEquals(expected, calculator.discountFor(total), 0.001);
}
@Test
void rejectsNegativeTotals() {
assertThrows(IllegalArgumentException.class, () -> calculator.discountFor(-1));
}
}
Los tests parametrizados necesitan el artifact junit-jupiter-params, que se incluye en la dependencia agregada junit-jupiter. (El código real que maneja dinero debería usar BigDecimal en lugar de double; aquí se mantiene simple.)
Qué hace buena a una prueba unitaria
- Rápida y determinista. Sin esperas, relojes, aleatoriedad ni red. Inyecta un
Clockfijo en lugar de llamar aLocalDate.now(). - Aislada. Las dependencias se sustituyen por test doubles allí donde harían el test lento o impredecible.
- Un comportamiento por test, con un nombre que lo enuncie, para que un fallo se explique por sí solo.
- Prueba el comportamiento, no la implementación. Haz aserciones sobre salidas y efectos observables, no sobre métodos privados, para que una refactorización no rompa los tests.
Prueba unitaria frente a prueba de integración
Una prueba unitaria comprueba tu lógica con todo lo demás sustituido. Una prueba de integración comprueba que los componentes reales funcionan juntos: tu repositorio contra una base de datos real, tu cliente contra un servicio real (o en contenedor). Las pruebas unitarias detectan errores de lógica a bajo coste; las de integración detectan errores de conexión, configuración, serialización y consultas que las unitarias eliminan con mocks. Una suite solo de pruebas unitarias puede estar completamente en verde mientras la aplicación ni siquiera arranca.
Cómo se define la “unidad”
No hay una respuesta universal. Algunos equipos consideran que la unidad es una sola clase y hacen mock de todos sus colaboradores. Otros consideran unidad un pequeño grupo de clases que implementa un comportamiento y solo sustituyen lo que cruza una frontera de proceso. El segundo estilo tiende a producir tests menos frágiles ante las refactorizaciones.