CodeGym /Cursos /Módulo 5. Spring /Lección 262: Unit-testing para microservicios: herramient...

Lección 262: Unit-testing para microservicios: herramientas y enfoques

Módulo 5. Spring
Nivel 21 , Lección 1
Disponible

Si comparas el desarrollo de microservicios con la construcción de un rascacielos, puedes decir que los unit tests son la comprobación de la fiabilidad de cada hilada de ladrillos. Imagina que uno de los ladrillos está defectuoso: el rascacielos puede venirse abajo. Con los microservicios pasa algo parecido: incluso un error pequeño en un servicio puede provocar problemas serios en la etapa de integración o en producción.

Los unit tests ayudan a:

  • Asegurarte de que la lógica de negocio básica funciona correctamente. Por ejemplo, un servicio bancario no debería regalarle al cliente un par de millones.
  • Aislar errores. Si un test falla, verás enseguida qué método o módulo es el culpable.
  • Facilitar el refactor del código. ¿Cambias la implementación? Asegúrate de que los tests antiguos siguen pasando.
  • Preservar tu salud mental como desarrollador. No hay nada peor que depurar un bug que aparece después del deploy.

Herramientas principales para unit testing

Para escribir unit tests en el ecosistema Java no tienes que reinventar la rueda. Ya está todo pensado desde hace tiempo:

  1. JUnit 5 — es el estándar de facto para testing en Java. Potente, flexible y bastante fácil de aprender.
  2. Mockito — biblioteca para crear mocks (objetos falsos) que permiten testear módulos de forma aislada.
  3. AssertJ — para aserciones más legibles y avanzadas en los tests (no obligatorio, pero útil).

JUnit 5: fundamentos del testing

JUnit te permite escribir unit tests que verifican métodos o clases concretas. Las anotaciones de JUnit más útiles:

  • @Test — marca un método como test.
  • @BeforeEach — se ejecuta antes de cada test.
  • @AfterEach — se ejecuta después de cada test.
  • @DisplayName — asigna un nombre legible al test.

Ejemplo de un test simple con JUnit:


import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatorTest {

    @Test
    void testAddition() {
        Calculator calculator = new Calculator();
        int result = calculator.add(1, 2);
        assertEquals(3, result, "1 + 2 debe ser igual a 3");
    }
}

Mockito: creación de mocks

Mockito es tu mejor amigo para testear dependencias. Los mocks permiten aislar el código bajo prueba, reemplazando dependencias reales por falsas. Sirven para testear solo tu código sin llamar a servicios externos, bases de datos, etc.

Ejemplo de uso de Mockito:


import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;

class OrderServiceTest {

    @Test
    void testCreateOrder() {
        // Creamos un mock para el repositorio
        OrderRepository repository = mock(OrderRepository.class);

        // Creamos OrderService con el repositorio falso
        OrderService service = new OrderService(repository);

        // Definimos el comportamiento del mock: devolvemos un valor ficticio
        when(repository.save(any(Order.class))).thenReturn(new Order(1L, "Test Order"));

        // Llamamos al método y comprobamos el resultado
        Order order = service.createOrder("Test Order");
        assertEquals(1L, order.getId(), "El ID del pedido debe ser 1");
        assertEquals("Test Order", order.getName(), "El nombre del pedido debe ser 'Test Order'");

        // Verificamos que el método save fue llamado realmente
        verify(repository).save(any(Order.class));
    }
}

Enfoques para escribir unit tests

Al testear servicios te encontrarás con varias dependencias: repositorios, otros servicios, APIs externas. Para testear la lógica de forma aislada necesitamos:

  1. Crear mocks para las dependencias.
  2. Definir su comportamiento usando métodos when (por ejemplo, when(repository.findById(1L)).thenReturn(mockEntity)).
  3. Comprobar que los métodos necesarios fueron llamados con los parámetros correctos (usando verify).

Ejemplo con varias dependencias:


import static org.mockito.Mockito.*;

class PaymentServiceTest {
    @Test
    void testProcessPayment() {
        PaymentGateway gateway = mock(PaymentGateway.class);
        NotificationService notification = mock(NotificationService.class);

        PaymentService service = new PaymentService(gateway, notification);

        when(gateway.process(any(PaymentRequest.class))).thenReturn(true);

        service.processPayment(new PaymentRequest(100));

        verify(gateway).process(any(PaymentRequest.class));
        verify(notification).sendNotification(any());
    }
}

Probar la lógica de negocio

Los unit tests deben comprobar no solo escenarios positivos, sino también casos límite. Por ejemplo:

  • Validación ante datos incorrectos. El servicio debería lanzar una excepción o devolver un error.
  • Comprobación ante datos "vacíos": listas vacías, valores nulos, etc.
  • Pruebas con los valores máximo y mínimo de los parámetros de entrada.

Ejemplo:


@Test
void testValidateInput_NullValue() {
    IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
        someService.validateInput(null);
    });
    assertEquals("Input cannot be null", exception.getMessage());
}

Qué probar y qué no

Es importante recordar que los unit tests no deberían:

  1. Probar bibliotecas externas (¿estás seguro de que tu StringUtils.capitalize() funciona? Espero que sí).
  2. Testear la interacción con la base de datos o la red (para eso están los integration tests y Testcontainers).

Los unit tests deberían:

  1. Probar la lógica de tu aplicación: métodos, funciones, clases.
  2. Comprobar casos límite: datos incorrectos, valores extremos.
  3. Verificar que las llamadas a las dependencias se realizan como deben (usando Mockito).

Errores típicos al escribir unit tests

  1. Los tests dependen del entorno externo. Por ejemplo, si el test accede a una base de datos real.
  2. Falta de aserciones. Si el test solo se ejecuta pero no verifica nada, no es un test.
  3. Confusión con los mocks. Una configuración de mocks demasiado compleja puede liarte a ti y a tus compañeros.
  4. Los tests acaban siendo más complicados que el propio código. Recuerda que los tests deben ser simples y claros.

Aplicación práctica

Los unit tests no solo te ayudan a comprobar que tu código funciona, sino que también gustarán a tu futuro empleador. En una entrevista te pueden preguntar: "¿Cómo escribes los tests?" y ahí podrás lucirte con tus conocimientos de JUnit, Mockito y estrategias de testing.

Además, unos buenos unit tests hacen que cambiar el código sea mucho más seguro. Si alguien en tu equipo rompe la lógica de negocio por accidente, los tests lo notarán de inmediato.

Enlaces a la documentación:

Así que coge JUnit, Mockito y ponte a escribir tests para nuestra aplicación de microservicios. ¡Un código probado es un buen código!

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION