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:
- El consumidor crea pruebas que describen sus expectativas del API del proveedor. Estas pruebas generan un "contrato".
- El contrato se publica (por ejemplo, en un repositorio centralizado).
- 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.
- 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:
- 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)); } } - Al ejecutar las pruebas del lado del consumidor, se genera un archivo de contrato (
.json). - Este archivo de contrato se publica en un Pact Broker u otro repositorio centralizado.
- 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)); } } - 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.