Implementación de pruebas unitarias para guava-retrying con JUnit

guava-retrying es una extensión de la biblioteca Guava que permite definir estrategias de reintento configurables para llamadas a funciones, como servicios remotos con disponibilidad intermitente. Este artículo explica cómo desarrollar pruebas unitairas robustas utilizando JUnit para validar la lógica de reintento.

Preparación del entorno de pruebas

Asegúrese de incluir las dependencias de JUnit y guava-retrying en el proyecto. Las pruebas se organizan en paquetes como com.github.retry.test y abarcan clases específicas para cada componente.

Clases de prueba esenciales:

  • RetryerConstructorTest: valida la configuración del constructor de reintentos.
  • PauseStrategyTest: verifica los cálculos de tiempo entre reintentos.
  • HaltStrategyTest: prueba las condiciones de parada.
  • AttemptTimerTest: examina los límites de tiempo por intento.

Pruebas de condiciones de reintento

Evalúe escenarios donde se deben activar reintentos, como ante excepciones o resultados inválidos. Ejemplo modificado:

@Test
public void reintentoPorExcepcionIo() throws ExecutionException, RetryException {
    Callable<string> operacion = simularErrorRedEnTresIntentos();
    Retryer<string> retryer = RetryerBuilder.<String>nuevoConstructor()
            .reintentarSiExcepcion(IOException.class)
            .construir();
    String resultado = retryer.llamar(operacion);
    assertNotNull(resultado);
}</string></string>

Validación de estrategias de pausa

Las estrategias de pausa determinan los intervalos entre reintentos. Pruebe diferentes configuraciones, como pausa fija o exponencial:

@Test
public void pausaExponencialConLimite() {
    PauseStrategy exponencial = PauseStrategies.pausaExponencial(50, TimeUnit.MILLISECONDS);
    long primerTiempo = exponencial.calcularTiempoDeSueño(intentoFallido(1, 0L));
    long segundoTiempo = exponencial.calcularTiempoDeSueño(intentoFallido(2, 0L));
    assertTrue(segundoTiempo > primerTiempo);
    // Verificar que el tiempo no exceda un máximo predefinido
    long tiempoFinal = exponencial.calcularTiempoDeSueño(intentoFallido(10, 0L));
    assertEquals(50, tiempoFinal);
}

Pruebas de estrategias de parada

Controle cuándo finalizan los reintentos. Implemente pruebas para límites basados en intentos o tiempo:

@Test
public void paradaPorLimiteDeIntentos() {
    HaltStrategy halt = HaltStrategies.paradaDespuesDeIntentos(4);
    assertFalse(halt.deberiaParar(intento(2, 0)));
    assertTrue(halt.deberiaParar(intento(4, 0)));
}

Técnicas avanzadas de prueba

Combine múltiples estrategias y pruebe funcionalidades como escuchas de reintento. Ejemplo para estrategias combinadas:

@Test
public void multiplesCondicionesDeReintento() throws ExecutionException, RetryException {
    Callable<Boolean> tarea = tareaConFallasMixtas();
    Retryer<Boolean> retryer = RetryerBuilder.<Boolean>nuevoConstructor()
            .reintentarSiResultado(Predicates.esNulo())
            .reintentarSiExcepcion(TimeoutException.class)
            .conEstrategiaDeParada(HaltStrategies.paradaDespuesDeIntentos(5))
            .construir();
    boolean exito = retryer.llamar(tarea);
    assertTrue(exito);
}

Para probar escuchas de reintento, registre eventos durante la ejecución:

@Test
public void escuchaRegistraIntentos() throws Exception {
    List<Intento<?>> intentos = new ArrayList<>();
    EscuchaReintento listener = new EscuchaReintento() {
        @Override
        public <V> onReintento(Intento<V> intento) {
            intentos.add(intento);
        }
    };
    Callable<String> callable = tareaConRetraso();
    Retryer<String> retryer = RetryerBuilder.<String>nuevoConstructor()
            .reintentarSiResultado(String::isEmpty)
            .conEscucha(listener)
            .construir();
    retryer.llamar(callable);
    assertEquals(3, intentos.size());
}

Mejores prácticas

Use @BeforeEach y @AfterEach para aislar el estado de las pruebas. Implemente pruebas parametrizadas para cubrir diferentes escenarios:

@ParameterizedTest
@CsvSource({"2, 100", "4, 200", "6, 400"})
void probarPausaFija(int intentos, long esperado) {
    PauseStrategy pause = PauseStrategies.pausaFija(esperado, TimeUnit.MILLISECONDS);
    long actual = pause.calcularTiempoDeSueño(intentoFallido(intentos, 0));
    assertEquals(esperado, actual);
}

Enfoque en casos límite, como reintentos máximos o tiempos de espera extremos.

Estructura de pruebas del proyecto

Las pruebas se organizan en archivos dedicados, como:

  • RetryerConstructorTest.java
  • PauseStrategyTest.java
  • HaltStrategyTest.java
  • AttemptTimerTest.java

Cada clase se enfoca en un componente, facilitando el mantenimiento.

Etiquetas: guava-retrying JUnit pruebas-unitarias reintentos java

Publicado el 6-19 16:46