JUnit 5


JUnit ha sido el proyecto de testing por defecto en el ecosistema Java durante años, desarrollado por Kent Beck. En el 2015, se realizó una campaña para recolectar fondos y continuar con el proyecto. Al inicio, el proyecto fue nombrado JUnit Lambda pero en estos días es conocido como JUnit 5. Recientemente, la versión 5.0.0-M2 ha sido liberada.

JUnit 5, es el conjunto de los siguientes proyectos:

  • JUnit Platform, proyecto base del nuevo framework de testing.

  • JUnit Jupiter, proyecto que provee las características propias de JUnit 5.

  • JUnit Vintage, proyecto que provee la compatibilidad con versiones anteriores como JUnit 3 y JUnit 4.

JUnit 5 provee plugins para asegurar la compatibilidad con las IDE’s y build tools como maven y gradle.

Lo nuevo en JUnit 5

Cambios entre JUnit 4 y JUnit 5

Algunas equivalencias entre las versiones:

JUnit 4 JUnit 5

org.junit.Assertions

org.junit.jupiter.api.Assertions

org.junit.Assume

org.junit.jupiter.api.Assumptions

@Ignore

@Disabled

@BeforeClass

@BeforeAll

@Before

@BeforeEach

@After

@AfterEach

@AfterClass

@AfterAll

@Category

@Tag

@RunWith

@ExtendWith

Modificador de acceso public no es necesario

A diferencia de las versiones previas, JUnit 5 no obliga a declarar todos los test con el modificador de acceso public.

class MyTest {

  @Test
  void someTest() {
    ...
  }

}

Composed Annotations

JUnit Jupiter permite el uso de Composed Annotations, es decir, crear anotaciones personalizadas y usarlas en los tests.

En el siguiente ejemplo, se puede apreciar que el método fastTest() ha sido anotado con @Tag("fast")

class MyTest {

  @Test
  @Tag("fast")
  void fastTest() {
    ...
  }

}

Para evitar duplicidad y poder reusar @Tag("fast"), se puede crear la anotación @Fast como se muestra a continuación.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
public @interface Fast {

}

La clase MyTest queda de la siguiente manera.

class MyTest {

  @Test
  @Fast
  void fastTest() {
    ...
  }

}

Multiple Assertions

assertAll asegura que todos los assert se ejecuten, y que todas las fallas que existan se muestren en el reporte.

class MyTest {

  @Test
  void someTest() {
    assertAll(
      () -> assertTrue(true),
      () -> assertTrue(1 == 1)
    );
  }

}

Assert Throws

assertThrows captura la excepción lanzada por el método a evaluar y asegura que la excepción sea la esperada.

class GsonTest {

  @Test
  void throwsJsonSyntaxException() {
    Gson gson = new Gson();
		String jsonData = "{{\"name\": \"Eddu\", \"lastname\": \"Melendez\"}";
    assertThrows(JsonSyntaxException.class, () -> gson.fromJson(jsonData, Person.class))
  }

}

Tests inner classes

JUnit Jupiter permite el uso de Inner Classes donde podemos crear más tests.

class GsonTest {

  @Test
  void instanceGson() {
      ...
  }

  @Nested
  class ToJson {

    @Test
    void buildSimpleJson() {
        ...
    }

  }

  @Nested
  class FromJson {

    @Test
    void buildSimpleObject() {
        ...
    }

  }

}

Nueva anotación @DisplayName

En versiones anteriores de JUnit, los nombres de los métodos eran explícitos para poder entender el test. JUnit Jupiter agrega una nueva anotación @DisplayName, la cual permite dar una mejor descripción al test.

class MyTest {

  @Test
  @DisplayName("La suma de 2 + 2 es igual 4")
  void sumaDosNumeros() {
    ...
  }

}

Eddú Meléndez

Java Software Engineer, Open Source Contributor