Java JUnit framework de pruebas unitarias

Java 常用类库Bibliotecas comunes de Java


JUnit es uno de los frameworks de pruebas unitarias más populares en el lenguaje de programación Java, utilizado para escribir y ejecutar pruebas automatizadas repetibles.

JUnit fue creado por Kent Beck y Erich Gamma, y es miembro de la familia xUnit. Las pruebas unitarias son el proceso de verificar y validar la parte más pequeña comprobable del software (generalmente métodos o clases).

Las características principales de JUnit incluyen:

  • Proporciona anotaciones para identificar métodos de prueba
  • Proporciona aserciones para verificar los resultados esperados
  • Admite suites de pruebas (Test Suite)
  • Proporciona ejecutores de pruebas (Test Runner)

¿Por qué se necesitan las pruebas unitarias?

Las pruebas unitarias son una parte indispensable del desarrollo de software moderno y aportan los siguientes beneficios:

  1. Detección temprana de problemas: Permite encontrar y corregir errores durante el desarrollo
  2. Mejora la calidad del código: Obliga a los desarrolladores a escribir código más modular y comprobable
  3. Función de documentación: Los propios casos de prueba son la mejor documentación del comportamiento del código
  4. Red de seguridad para la refactorización: Garantiza que modificar el código no rompa la funcionalidad existente
  5. Reduce el tiempo de depuración: Localiza rápidamente el origen del problema

Usar JUnit en proyectos

Para JUnit 5:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

Para JUnit 4:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

Fundamentos de JUnit 5

JUnit 5 es la versión más reciente y se compone de tres módulos principales:

  • JUnit Platform (la base para ejecutar pruebas)
  • JUnit Jupiter (el nuevo modelo de programación y extensión)
  • JUnit Vintage (admite la ejecución de pruebas de JUnit 3 y 4)

Anotaciones básicas

Anotaciones de versiones anteriores:

  • @Test: Marca un método como método de prueba

  • @Before: Se ejecuta antes de cada método de prueba

  • @After: Se ejecuta después de cada método de prueba

  • @BeforeClass: Se ejecuta antes de todas las pruebas (método estático)

  • @AfterClass: Se ejecuta después de todas las pruebas (método estático)

  • @Ignore: Ignora el método de prueba

Ejemplo

import org.junit.*;

public class CalculatorTest {
   
    @BeforeClass
    public static void setUpBeforeClass() {
        System.out.println("Before all tests");
    }
   
    @Before
    public void setUp() {
        System.out.println("Before each test");
    }
   
    @Test
    public void testAddition() {
        Calculator calculator = new Calculator();
        int result = calculator.add(2, 3);
        Assert.assertEquals(5, result);
    }
   
    @Test
    @Ignore("Not implemented yet")
    public void testSubtraction() {
        // Código de prueba
    }
   
    @After
    public void tearDown() {
        System.out.println("After each test");
    }
   
    @AfterClass
    public static void tearDownAfterClass() {
        System.out.println("After all tests");
    }
}

JUnit 5 es la nueva generación, con las siguientes anotaciones nuevas:

  • @BeforeEachReemplaza@Before

  • @AfterEachReemplaza@After

  • @BeforeAllReemplaza@BeforeClass

  • @AfterAllReemplaza@AfterClass

  • @DisabledReemplaza@Ignore

Ejemplo

import org.junit.jupiter.api.*;

@Test
void testMethod() {
    // Código de prueba
}

@BeforeEach
void setUp() {
    // Se ejecuta antes de cada método de prueba
}

@AfterEach
void tearDown() {
    // Se ejecuta después de cada método de prueba
}

@BeforeAll
static void initAll() {
    // Se ejecuta una vez antes de todos los métodos de prueba
}

@AfterAll
static void tearDownAll() {
    // Se ejecuta una vez después de todos los métodos de prueba
}

Métodos de aserción comunes

JUnit proporciona una gran variedad de métodos de aserción para verificar los resultados de las pruebas:

  • assertEquals(expected, actual)

  • assertTrue(condition)

  • assertFalse(condition)

  • assertNull(object)

  • assertNotNull(object)

  • assertSame(expected, actual)(Comprueba si es el mismo objeto)

  • assertNotSame(unexpected, actual)

  • assertArrayEquals(expectedArray, actualArray)

Ejemplo

import static org.junit.jupiter.api.Assertions.*;

@Test
void testAssertions() {
    // Aserción de igualdad
    assertEquals(expected, actual);
   
    // Aserción de verdadero
    assertTrue(condition);
   
    // Aserción de nulo
    assertNull(object);
   
    // Aserción de excepción
    assertThrows(ExpectedException.class, () -> {
        // Código que lanzará una excepción
    });
   
    // Aserción de tiempo de espera
    assertTimeout(Duration.ofMillis(100), () -> {
        // Código que debe completarse dentro del tiempo especificado
    });
}

Escribir tu primera prueba JUnit

Aprendamos a escribir pruebas JUnit con un ejemplo sencillo.

1. Crear la clase bajo prueba

Ejemplo

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
   
    public int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("El divisor no puede ser cero");
        }
        return a / b;
    }
}

2. Crear la clase de prueba

Ejemplo

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    private Calculator calculator;
   
    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }
   
    @Test
    void testAdd() {
        assertEquals(5, calculator.add(2, 3));
    }
   
    @Test
    void testDivide() {
        assertEquals(2, calculator.divide(6, 3));
    }
   
    @Test
    void testDivideByZero() {
        assertThrows(ArithmeticException.class, () -> {
            calculator.divide(1, 0);
        });
    }
}

Características avanzadas de JUnit

Pruebas parametrizadas

JUnit 5 proporciona la@ParameterizedTestanotación, que permite ejecutar la misma prueba varias veces con diferentes parámetros:

Ejemplo

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithValueSource(int argument) {
    assertTrue(argument > 0 && argument < 4);
}

Ciclo de vida de las pruebas

Comprender el ciclo de vida de las pruebas JUnit es importante para escribir pruebas efectivas:

  1. @BeforeAllEjecución del método (solo una vez)
  2. Para cada método de prueba:
    • Crear una instancia de la clase de prueba
    • @BeforeEachEjecución del método
    • Ejecución del método de prueba
    • @AfterEachEjecución del método
  3. @AfterAllEjecución del método (solo una vez)

Suite de pruebas

Se puede utilizar la@Suiteanotación para agrupar varias clases de prueba y ejecutarlas juntas:

Ejemplo

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({CalculatorTest.class, AnotherTest.class})
public class TestSuite {
}

Mejores prácticas

  1. Nombrado de pruebas: El nombre del método de prueba debe expresar claramente su intención, comoshouldReturnTrueWhenInputIsValid()
  2. Responsabilidad única: Cada método de prueba solo prueba un punto funcional
  3. Pruebas independientes: No debe haber dependencias entre las pruebas
  4. Retroalimentación rápida: Mantén las pruebas ejecutándose rápidamente
  5. Cobertura de pruebas: Busca una cobertura razonable, pero no persigas ciegamente el 100%
  6. Datos de prueba: Usa datos de prueba significativos
  7. Evita probar detalles de implementación: Prueba el comportamiento, no la implementación

Preguntas frecuentes

¿Cuál es la diferencia entre JUnit 4 y JUnit 5?

Las principales diferencias incluyen:

  • JUnit 5 requiere Java 8 o superior
  • Las anotaciones se mueven del paqueteorg.junital paqueteorg.junit.jupiter.apiPaquete
  • @Beforey@Aftercambia a@BeforeEachy@AfterEach
  • @BeforeClassy@AfterClasscambia a@BeforeAlly@AfterAll
  • JUnit 5 introduce un modelo de extensiones para reemplazar las reglas de JUnit 4

¿Cómo ejecutar pruebas JUnit?

Se pueden ejecutar pruebas JUnit de las siguientes maneras:

  1. Haz clic derecho en la clase o método de prueba en el IDE y selecciona "Ejecutar"
  2. Usando Maven:mvn test
  3. Usando Gradle:gradle test
  4. Usando el lanzador de consola de JUnit

¿Cómo probar métodos privados?

Generalmente no se recomienda probar directamente los métodos privados, sino probarlos indirectamente a través de métodos públicos. Si es necesario probar métodos privados, se puede considerar:

  1. Usar reflexión
  2. Cambiar el método a paquete privado (sin modificador) y crear una clase de prueba con la misma estructura de paquete en el directorio de pruebas
  3. Refactorizar el código para extraer la lógica del método privado a una clase separada

Resumen

JUnit es una herramienta de pruebas imprescindible para los desarrolladores de Java. Dominarla puede mejorar significativamente la calidad del código y la eficiencia del desarrollo. Comienza con pruebas unitarias simples y aprende gradualmente características más avanzadas, como pruebas parametrizadas, suites de pruebas, etc. Recuerda que las buenas pruebas deben recibir la misma importancia que el código de producción; mantener el código de prueba limpio y mantenible es igualmente importante.

Java 常用类库Bibliotecas comunes de Java

Otras extensiones