Cuando dos componentes se comunican, existe un acuerdo entre ellos. Uno produce información o comportamiento, y otro lo consume. Si ese acuerdo cambia sin control, la integración puede romperse aunque cada componente funcione correctamente de forma aislada.
Las pruebas de contratos ayudan a verificar que productores y consumidores sigan respetando esos acuerdos. Son especialmente útiles en sistemas con servicios internos, APIs, eventos, colas o módulos mantenidos por equipos distintos.
En este tema veremos qué son estas pruebas, qué verifican y cómo se relacionan con las pruebas de integración.
En una integración, el productor es el componente que entrega datos, eventos, respuestas o comportamiento. El consumidor es el componente que usa eso que el productor entrega.
Ejemplos:
La integración funciona mientras productor y consumidor compartan la misma expectativa.
Un contrato define qué puede esperar un consumidor del productor. Puede estar escrito en documentación formal, especificaciones, esquemas, ejemplos o pruebas.
Un contrato puede incluir:
Las pruebas de contratos verifican que un productor y un consumidor sigan siendo compatibles.
Pueden comprobar:
Una prueba de integración común puede ejecutar productor y consumidor juntos para verificar un flujo. Una prueba de contrato se concentra específicamente en el acuerdo entre ambos.
| Tipo de prueba | Foco principal | Ejemplo |
|---|---|---|
| Integración común | Colaboración en un escenario concreto. | Crear una orden y enviar notificación. |
| Contrato | Compatibilidad entre productor y consumidor. | El evento de orden creada contiene los campos que notificaciones necesita. |
Ambas son complementarias. Las pruebas de contrato reducen el riesgo de incompatibilidades antes de ejecutar flujos más amplios.
En APIs, el contrato suele incluir rutas, métodos, parámetros, encabezados, cuerpos de solicitud, cuerpos de respuesta y códigos de estado.
Por ejemplo, un consumidor puede esperar que la API de usuarios devuelva:
id como identificador.nombre como texto.email como texto obligatorio.estado con valores conocidos.Si el productor cambia email por correo sin coordinar, el consumidor puede romperse.
En sistemas asíncronos, el contrato puede estar en la estructura de un evento o mensaje. El consumidor no llama al productor directamente, pero depende de lo que el productor publica.
Un evento de orden creada podría incluir:
Las pruebas de contrato pueden verificar que el productor publique eventos con la estructura que los consumidores esperan.
Los errores también forman parte del contrato. Un consumidor necesita saber cómo interpretar fallas conocidas.
Conviene definir y probar:
Si el productor cambia la forma de reportar errores, el consumidor puede dejar de manejar casos importantes.
En algunos equipos se usa el enfoque de contratos impulsados por consumidores. La idea es que los consumidores expresan qué necesitan del productor. Luego el productor verifica que puede cumplir esas expectativas.
Esto ayuda a evitar que el productor cambie una respuesta pensando que nadie la usa, cuando en realidad un consumidor depende de ciertos campos.
Este enfoque es útil cuando:
No todos los cambios de contrato tienen el mismo riesgo. Algunos son compatibles y otros pueden romper consumidores.
| Cambio | Riesgo | Comentario |
|---|---|---|
| Agregar un campo opcional. | Bajo | Suele ser compatible si los consumidores ignoran campos desconocidos. |
| Eliminar un campo usado. | Alto | Puede romper consumidores inmediatamente. |
| Cambiar tipo de dato. | Alto | Un número como texto puede generar errores de interpretación. |
| Agregar un nuevo valor de estado. | Medio o alto | Depende de si el consumidor maneja valores desconocidos. |
| Cambiar formato de error. | Alto | Puede impedir que el consumidor responda adecuadamente. |
Cuando un contrato necesita cambiar de forma incompatible, puede ser necesario versionarlo. El versionado permite que consumidores antiguos sigan usando una versión mientras migran a otra.
Puede versionarse:
Las pruebas de contrato ayudan a verificar que cada versión siga cumpliendo lo prometido a sus consumidores.
Un consumidor no debería depender de detalles que no forman parte del contrato. Si lo hace, se vuelve frágil.
Ejemplos de malas dependencias:
Las pruebas de contrato también pueden revelar expectativas incorrectas del consumidor.
Supongamos que una aplicación consume datos de un servicio de usuarios. El contrato mínimo podría ser:
| Campo | Tipo | Uso del consumidor |
|---|---|---|
id |
Texto o número según contrato. | Identificar al usuario en operaciones posteriores. |
nombre |
Texto. | Mostrar el nombre en pantalla. |
email |
Texto. | Enviar notificaciones. |
estado |
Texto con valores conocidos. | Determinar si puede operar. |
Una prueba de contrato puede comprobar que el productor sigue entregando esos campos con el tipo y significado esperados.
Supongamos un evento orden_creada. El consumidor de notificaciones necesita saber a quién avisar y qué operación ocurrió.
El contrato podría indicar que el evento debe incluir:
eventId: identificador único del evento.ordenId: identificador de la orden.clienteId: identificador del cliente.email: contacto para notificación.total: importe de la orden.version: versión del contrato del evento.Si el productor deja de enviar email, el consumidor no podrá enviar la notificación aunque el evento siga publicándose.
Al trabajar con contratos, suelen aparecer errores como:
Para revisar una prueba de contrato, podemos preguntar:
Las pruebas de contratos son una herramienta poderosa para reducir fallas de integración entre componentes que evolucionan. Ayudan a que productores y consumidores mantengan acuerdos claros y verificables.
Estas pruebas no reemplazan todos los escenarios de integración, pero permiten detectar rupturas de compatibilidad antes de ejecutar flujos más amplios.
En el próximo tema veremos la integración con colas, eventos y procesos asíncronos.