JUnit es un framework estándar para pruebas unitarias en el ecosistema Java y Kotlin, utilizado en el desarrollo de Android para verificar la lógica de negocio a nivel de componentes aislados. El framework proporciona un conjunto de anotaciones, métodos de aserción y un Test Runner para la detección y ejecución automática de pruebas. Según JUnit.org, la biblioteca sigue siendo la solución más popular para pruebas unitarias en el ecosistema JVM: más del 70% de los proyectos Java utilizan JUnit en alguna de sus versiones.
Puntos clave
JUnit es un framework de código abierto para escribir y ejecutar pruebas unitarias repetibles en Java y Kotlin. Forma parte del ecosistema xUnit, una familia de frameworks basados en la arquitectura de Kent Beck y Erich Gamma, y es la herramienta de prueba estándar en Android Studio e IntelliJ IDEA.
La tarea principal de JUnit es aislar un pequeño fragmento de código (método, clase) y verificar su comportamiento en condiciones controladas. Las pruebas se escriben como clases Java/Kotlin comunes con anotaciones, y el framework se encarga de la detección de pruebas, la gestión del ciclo de vida y la recopilación de estadísticas de ejecución.
La primera versión de JUnit apareció en 1997 y cambió radicalmente el enfoque de desarrollo, popularizando las prácticas de Test-Driven Development (TDD). Hoy en día, JUnit 5 (Jupiter) es la versión actual, completamente rediseñada con una arquitectura modular compatible con Java 8+ y extensiones.
El mecanismo de ejecución de JUnit se basa en el patrón Test Runner, que escanea el classpath, encuentra métodos con la anotación @Test, crea una instancia de la clase de prueba y ejecuta los métodos en un orden específico. El Test Runner gestiona el ciclo de vida: BeforeAll → BeforeEach → Test → AfterEach → AfterAll.
JUnit envuelve cada método de prueba en una instancia de clase separada, garantizando el aislamiento entre pruebas. Esto significa que los campos de la clase no conservan el estado entre diferentes métodos @Test — cada prueba comienza con un objeto limpio.
La prueba más simple en JUnit es un método con la anotación @Test que llama al código bajo prueba y verifica el resultado mediante una afirmación. Si la afirmación falla, la prueba se considera fallida y JUnit informa del error.
@Test
void additionShouldReturnCorrectSum() {
var calculator = new Calculator();
var result = calculator.add(2, 3);
assertEquals(5, result);
}
El Test Runner encuentra automáticamente dicho método, lo ejecuta e informa del resultado. Si el método no lanza una excepción — la prueba pasa (green). Si una afirmación falla — la prueba falla (red).
Las anotaciones de JUnit definen cuándo y cómo debe ejecutarse el código de prueba. En JUnit 5, las anotaciones se encuentran en el paquete org.junit.jupiter.api y cubren todas las etapas: preparación de datos, ejecución de la prueba, limpieza de recursos.
| Anotación | Propósito | Se ejecuta |
|---|---|---|
| @Test | Marca un método de prueba | Una vez por llamada |
| @BeforeEach | Preparación antes de cada prueba | Antes de cada @Test |
| @BeforeAll | Inicialización única de la clase | Una vez antes de todas las pruebas |
| @AfterEach | Limpieza después de cada prueba | Después de cada @Test |
| @AfterAll | Finalización única de la clase | Una vez después de todas las pruebas |
| @DisplayName | Nombre legible de la prueba | Decoración |
Consideremos una clase de prueba completa con un ciclo de vida adecuado. El método setUp crea una instancia nueva de Calculator antes de cada prueba, y tearDown libera recursos — por ejemplo, cerrando descriptores de archivo o conexiones de base de datos.
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@Test
void subtractionShouldReturnCorrectResult() {
int result = calculator.subtract(10, 4);
assertEquals(6, result);
}
@AfterEach
void tearDown() {
calculator.reset();
}
}
Las afirmaciones son métodos estáticos que comparan el resultado real con el esperado y lanzan una excepción si no coinciden. JUnit 5 ofrece la clase org.junit.jupiter.api.Assertions con más de 25 métodos para diferentes escenarios de verificación — desde la comparación simple de valores hasta la comprobación de tiempos de espera y afirmaciones agrupadas.
Especial atención merece el método assertThrows, que permite verificar que el código maneja correctamente situaciones de error — división por cero, paso de null, superación de límites.
@Test
void divisionByZeroShouldThrowException() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Las pruebas parametrizadas permiten ejecutar el mismo método de prueba con diferentes conjuntos de argumentos. En JUnit 5, esto se hace mediante la anotación @ParameterizedTest combinada con una fuente de datos — @ValueSource, @CsvSource, @MethodSource o @EnumSource.
Este enfoque reduce radicalmente la duplicación de código: en lugar de diez pruebas idénticas para diferentes valores, se escribe un único método parametrizado. Según el Google Testing Blog, la parametrización reduce el volumen de código de prueba en un 40–60% sin perder cobertura.
La anotación @CsvSource pasa múltiples filas separadas por comas a la prueba. Cada fila corresponde a una ejecución de la prueba. JUnit convierte automáticamente los valores de cadena a los tipos requeridos: int, long, String y otros.
@ParameterizedTest
@CsvSource({
"1, 1, 2",
"2, 3, 5",
"10, 20, 30",
"-1, 1, 0"
})
void additionWithMultipleInputs(int a, int b, int expected) {
assertEquals(expected, a + b);
}
Cuando los datos de entrada son más complejos que números o cadenas simples, se utiliza @MethodSource. Hace referencia a un método estático que devuelve un Stream de argumentos — por ejemplo, un Stream de Arguments o un Stream de objetos User para probar la capa DAO.
En el desarrollo de Android, JUnit se utiliza junto con AndroidX Test, que proporciona extensiones para probar Activity, Content Provider y otros componentes de Android. JUnit se encarga de las pruebas unitarias que se ejecutan en la JVM sin emulador, mientras que AndroidX Test se encarga de las pruebas instrumentadas en el dispositivo.
Para añadir JUnit 5 a un proyecto Android, basta con incluir la dependencia org.junit.jupiter:junit-jupiter en el build.gradle a nivel de módulo. El plugin AGP de Gradle admite la ejecución de pruebas JUnit 5 en la JVM a través del Test Runner estándar.
// build.gradle.kts
android {
testOptions {
unitTests.isIncludeAndroidResources = true
}
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
testImplementation("androidx.test:core-ktx:1.6.1")
}
En la práctica, JUnit se utiliza más a menudo para probar ViewModel y repositorios — capas que no requieren contexto de Android ni emulador. Una prueba de este tipo se ejecuta en milisegundos y puede ejecutarse cientos de veces sin perder tiempo.
JUnit 5 (Jupiter) no es solo una nueva versión, sino una plataforma completamente rediseñada dividida en tres módulos: JUnit Platform (ejecución de pruebas en JVM), JUnit Jupiter (API para escribir pruebas) y JUnit Vintage (compatibilidad inversa con JUnit 4). Esta modularidad permite conectar diferentes Test Engines — por ejemplo, Spek para Kotlin o TestNG.
| Característica | JUnit 4 | JUnit 5 |
|---|---|---|
| Paquete | org.junit | org.junit.jupiter |
| Anotación base | @Test (de junit.framework) | @Test (de org.junit.jupiter.api) |
| Before/After | @Before, @After, @BeforeClass | @BeforeEach, @AfterEach, @BeforeAll |
| Parametrizadas | @RunWith(Parameterized.class) | @ParameterizedTest + @ValueSource |
| Extensión | @Rule, @ClassRule | @ExtendWith, API más flexible |
| Java min | Java 5 | Java 8+ |
La migración de JUnit 4 a JUnit 5 no requiere reescribir todas las pruebas — basta con añadir JUnit Vintage Engine y las pruebas antiguas seguirán funcionando. Se recomienda escribir las pruebas nuevas con JUnit 5 para aprovechar las extensiones, las aserciones lambda y el soporte integrado de parametrización.
Preguntas frecuentes
JUnit es un framework para escribir y ejecutar pruebas, mientras que Mockito es una biblioteca para crear objetos mock. Se utilizan juntos: JUnit gestiona la ejecución de la prueba y Mockito reemplaza las dependencias de la clase bajo prueba.
Sí, JUnit 5 es totalmente compatible con proyectos Android. Para pruebas unitarias, basta con añadir la dependencia junit-jupiter en build.gradle. Las pruebas instrumentadas siguen funcionando a través de AndroidX Test Runner.
Como mínimo, basta con una única anotación @Test antes del método. Para inicialización y limpieza se recomiendan @BeforeEach y @AfterEach, pero no son obligatorias.
El Test Runner es un componente de JUnit que escanea el classpath, encuentra métodos con la anotación @Test, crea instancias de clases de prueba y ejecuta las pruebas. En JUnit 5, este papel lo desempeña JUnit Platform con los Test Engines conectados.
Use assertThrows(Class, Executable) — acepta el tipo de excepción esperada y una lambda con la llamada al método. JUnit verifica que la excepción se haya lanzado realmente y la devuelve para una inspección adicional.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también