Sobes.tech
Middle+

Habla sobre las pruebas de contrato de un microservicio.

sobes.tech AI

Respuesta de la IA

Las pruebas de contrato se centran en verificar la interacción entre microservicios a nivel de su API (contrato). El objetivo es asegurarse de que el consumidor (servicio que utiliza la API) y el proveedor (servicio que proporciona la API) cumplen con un "contrato" determinado (esquema de solicitudes/respuestas, formato de datos, expectativas).

Principios básicos:

  • Consumidor-dirigido: Las pruebas se basan en las expectativas del consumidor. El consumidor determina qué datos y formatos necesita.
  • Pruebas bidireccionales: Se verifica tanto la capacidad del consumidor (para trabajar con el contrato actual) como la del proveedor (para cumplir con las expectativas del consumidor).
  • Velocidad: Las pruebas se ejecutan rápidamente, a menudo en un pipeline CI/CD, ya que no requieren desplegar todos los servicios dependientes.

El proceso generalmente incluye:

  1. El consumidor crea pruebas que describen sus expectativas del API del proveedor. Estas pruebas generan un "contrato".
  2. El contrato se publica (por ejemplo, en un repositorio centralizado).
  3. El proveedor usa el contrato publicado para verificar su implementación del API. Ejecuta las pruebas (generalmente en el lado del proveedor), que verifican si su API cumple con el contrato.
  4. En caso de discrepancia entre las expectativas del consumidor y la implementación del proveedor, la prueba falla, indicando una violación del contrato.

Herramientas:

  • Pact (el más popular)
  • Spring Cloud Contract
  • Swagger/OpenAPI con herramientas de validación

Ventajas:

  • Detección temprana de errores de integración: Los problemas de compatibilidad se detectan antes del despliegue.
  • Reducción de la necesidad de pruebas de integración: Disminuye la dependencia de pruebas de extremo a extremo complejas y lentas.
  • Pruebas independientes: Permite probar los servicios de forma independiente.
  • Definición clara de expectativas: Define explícitamente el contrato entre servicios.

Desventajas:

  • No reemplaza completamente las pruebas de integración (solo verifica la interacción a nivel de API).
  • Requiere disciplina en la gestión de versiones de los contratos.
  • Puede ser más complejo para servicios con contratos muy complejos.

Ejemplo de uso con Pact:

  1. El consumidor (por ejemplo, el servicio Order Service) usa la biblioteca Pact para crear pruebas del lado del consumidor.
    // Ejemplo de prueba del consumidor con Pact JVM
    @ExtendWith(PactConsumerTestExt.class)
    @PactTestFor(providerName = "ProductService", port = "8080")
    public class ProductServiceContractTest {
    
        @Pact(consumer = "OrderService")
        public RequestResponsePact createPact(PactDslWithRequest r) {
            return r.given("a product with id 1 exists")
                    .uponReceiving("a request for product by id")
                    .path("/products/1")
                    .method("GET")
                    .willRespondWith()
                    .status(200)
                    .headers(Map.of("Content-Type", "application/json"))
                    .body(new PactDslJsonBody()
                            .stringValue("id", "1")
                            .stringValue("name", "Laptop")
                            .numberType("price", 1200.00))
                    .toPact();
        }
    
        @Test
        void testGetProductById(MockServer mockServer) throws IOException {
            // Lógica para llamar a la API del proveedor a través de mockServer
            // Verifica que el consumidor maneja correctamente la respuesta mock
            HttpResponse response = Request.Get(mockServer.getUrl() + "/products/1").execute().returnResponse();
            assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        }
    }
    
  2. Al ejecutar las pruebas del lado del consumidor, se genera un archivo de contrato (.json).
  3. Este archivo de contrato se publica en un Pact Broker u otro repositorio centralizado.
  4. El proveedor (Product Service) usa la biblioteca Pact (por ejemplo, Pact Provider Verifier) para verificar su implementación del API basada en el contrato obtenido del Pact Broker.
    // Ejemplo de prueba del proveedor con Pact Provider Verifier
    @Provider("ProductService")
    @PactFolder("relative/path/to/pacts") // o usar Pact Broker
    public class ProductServiceVerificationTest {
    
        @TestTemplate
        @ExtendWith(PactVerificationInvocationContextProvider.class)
        public void verifyPact(PactVerificationContext context) {
            context.verifyInteraction();
        }
    
        @State("a product with id 1 exists")
        public void productWithId1Exists() {
            // Lógica para preparar el estado de los datos en el servicio del proveedor para la prueba
        }
    
        // Añadir la URL del proveedor donde se ejecuta el servicio en prueba
        @BeforeEach
        void beforeEach(PactVerificationContext context) {
            context.setTarget(new HttpTestTarget("localhost", 8080));
        }
    }
    
  5. El verificador en el lado del proveedor llama a la API real del proveedor según la especificación del contrato y compara la respuesta recibida con la esperada en el contrato.

La prueba de contrato es una práctica importante para garantizar la fiabilidad y mantenibilidad de sistemas basados en microservicios.