# Contract Testing de APIs y microservicios con Pact

**Categoría:** Testing y QA · **Nivel:** Intermedio · **Lectura:** 14 min
**Publicada:** 2026-07-27 · **Actualizada:** 2026-07-27 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/testing/contract-testing-de-apis-con-pact/

Probar que dos servicios se entienden sin levantarlos juntos. Cómo funciona el flujo dirigido por el consumidor, qué hace el broker, y por qué la pregunta «¿puedo desplegar?» pasa a tener una respuesta con datos.

## Respuesta rápida

El **contract testing** es, según la documentación de Pact, una técnica para probar un punto de integración **revisando cada aplicación por separado**, para asegurar que los mensajes que envía o recibe cumplen un entendimiento compartido documentado en un **contrato**. Funciona en dos fases: en el **consumidor**, los tests corren contra un proveedor simulado y generan un **archivo de pacto** que describe cada interacción; en el **proveedor**, cada petición del pacto se reproduce contra el servicio real y se comprueba que la respuesta contenga **al menos** los datos que el consumidor declaró necesitar. El **broker** guarda contratos y resultados, y responde con datos la pregunta «¿puedo desplegar esta versión?».

## El problema que resuelve

Con dos servicios, probar que se entienden es fácil: los levantás juntos y listo. Con quince servicios que se llaman entre sí, ese enfoque se desarma, y siempre por las mismas tres razones:

- **Hay que levantar todo junto.** Cada prueba necesita el resto del sistema corriendo, con sus bases de datos y sus dependencias.
- **Es lenta y frágil.** Cualquier servicio caído, cualquier dato inconsistente, cualquier lentitud de red hace fallar pruebas que no tenían nada que ver.
- **Cuando falla, no dice quién rompió qué.** Este es el peor de los tres: una prueba roja en un entorno compartido inicia una investigación entre equipos en lugar de señalar al responsable.

Y hay un problema anterior, más silencioso: **el proveedor de una API no sabe quién usa qué**. Cuando alguien quiere renombrar un campo, la pregunta «¿esto rompe a alguien?» no tiene respuesta, así que se elige entre no cambiar nada nunca o cambiar y esperar.

## Qué es, con precisión

> **La definición, de la documentación de Pact.** «El contract testing es una técnica para probar un punto de integración **comprobando cada aplicación por separado** para asegurar que los mensajes que envía o recibe se ajustan a un entendimiento compartido que está documentado en un *contrato*.»

La expresión que hace todo el trabajo es **«por separado»**. El contrato existe justamente para que cada lado pueda verificarse solo, en su propio pipeline, sin el otro corriendo. De ahí salen las tres ventajas que son el reverso exacto de los tres problemas anteriores: es rápido, no es frágil, y cuando falla se sabe qué lado incumplió.

**Pact** es la herramienta de código abierto más difundida para hacerlo. Es *code-first*: el contrato no se escribe en un documento aparte, se **genera ejecutando los tests del consumidor**.

## Consumidor y proveedor

Dos términos y conviene fijarlos bien, porque todo lo demás depende de ellos:

- **Consumidor:** la aplicación que *pide* los datos. Un frontend, un servicio que llama a otro, un trabajo que lee de una cola.
- **Proveedor:** la aplicación que *entrega* los datos. Una API, un servicio, quien publica en la cola.

Pact usa estos términos y no «cliente» y «servidor» de forma deliberada: el vocabulario se aplica igual a la comunicación por mensajes, donde las etiquetas cliente-servidor no encajan. Un mismo servicio suele ser **consumidor de unos y proveedor de otros** al mismo tiempo, y va a tener contratos en los dos roles.

## Por qué lo dirige el consumidor

Pact usa el enfoque **dirigido por el consumidor**: el contrato «se genera durante la ejecución de los tests automatizados del consumidor». No lo escribe quien publica la API, lo produce quien la usa.

La lógica es sólida: **quien consume es el único que sabe qué necesita de verdad**. Un proveedor que documenta su API describe todo lo que ofrece; un consumidor que genera un pacto documenta exactamente los campos que usa, ni uno más.

La documentación describe el enfoque como **«contrato por ejemplo»**: cada caso de prueba describe un par concreto de petición y respuesta que después se verifica, en lugar de una especificación abstracta.

> **El beneficio que se aprecia a los seis meses.** El proveedor deja de trabajar a ciegas. Cuando alguien pregunta «¿puedo quitar este campo?», la respuesta ya no es una opinión: está en los contratos publicados. Si ningún consumidor lo declaró, se quita sin drama; si tres lo usan, se sabe con quién hay que hablar. **Esa información es el producto principal del contract testing**, más incluso que las pruebas en sí.

## Fase 1: en el consumidor

![El flujo del contract testing con Pact. Arriba, la comparación entre pruebas de punta a punta y contract testing. En la fase del consumidor: se registran petición y respuesta esperadas, el consumidor hace una petición real contra un proveedor simulado, el simulado compara y responde, y el consumidor confirma que entendió; al final se genera el archivo de pacto. En medio, el broker. En la fase del proveedor, cada petición se envía al proveedor real y la respuesta se compara con la mínima esperada.](../../assets/img/guias/contract-testing-de-apis-con-pact-flujo.svg)

La documentación de Pact describe cuatro pasos, y el detalle importa porque explica por qué el resultado es confiable:

1. **Se registran la petición y la respuesta esperadas.** Usando el lenguaje de Pact, se declara qué se va a pedir y qué se espera recibir. Ese registro se hace contra un servicio simulado.
2. **El código del consumidor hace una petición real.** Y acá está la clave: *real*, contra el proveedor simulado que crea el propio marco. No se simula la llamada: se ejecuta el código de tu cliente HTTP con toda su configuración.
3. **El simulado compara y responde.** Compara la petición que llegó con la esperada, y si coincide emite la respuesta declarada.
4. **El consumidor confirma que la entendió.** El test verifica que tu código procesó esa respuesta correctamente.

El marco exige que «los tests de Pact solo son exitosos si cada paso se completa sin error». Esa doble comprobación —tu código pide bien *y* entiende bien— es lo que evita el problema clásico de los *mocks* escritos a mano: un simulacro que devuelve lo que tu código espera, aunque el servicio real devuelva otra cosa.

Al terminar, «el marco de Pact genera un *archivo de pacto* que describe cada interacción». Ese archivo JSON es el contrato.

## Fase 2: en el proveedor

La segunda fase invierte el flujo. Cada interacción del pacto se **reproduce contra el proveedor real**: «en la verificación del proveedor, cada petición se envía al proveedor, y la respuesta que genera se compara con la respuesta mínima esperada descrita en el test del consumidor».

Tres cosas que conviene notar de esta fase:

- **El proveedor corre de verdad.** Con su código, sus validaciones y su serialización. Lo que se simula, si hace falta, son sus dependencias.
- **Corre en el pipeline del proveedor.** No hace falta el consumidor: solo el archivo de pacto.
- **Necesita estados previos.** Si el pacto dice «pedido 42 existe y está pagado», el proveedor tiene que poder llegar a ese estado antes de responder. Pact llama a eso *provider states*, y es la parte que más trabajo de configuración lleva.

## La respuesta mínima esperada

Este es el concepto más elegante del diseño y el que hay que entender para no usarlo mal. La verificación pasa cuando «cada petición genera una respuesta que contiene **al menos** los datos descritos en la respuesta mínima esperada».

| Cambio en el proveedor | ¿Rompe el contrato? | Por qué |
|---|---|---|
| Agregar un campo nuevo a la respuesta | **No** | El consumidor nunca dijo que la respuesta debiera tener solo esos campos |
| Quitar un campo que un consumidor declaró usar | Sí | Falta un dato que estaba en la respuesta mínima |
| Renombrar ese campo | Sí | Equivale a quitarlo |
| Cambiar su tipo, de número a texto | Sí | El consumidor declaró el tipo que necesita |
| Cambiar el código de estado | Sí | Es parte de la interacción declarada |
| Agregar un campo obligatorio a la petición | Sí | La petición del consumidor ya no sería válida |

Fijate que ese conjunto es **exactamente el de los cambios que en producción romperían a alguien**, y ninguno más. Por eso el contract testing no se convierte en un freno: la evolución compatible pasa sin ruido y solo se detiene lo que de verdad rompe.

## El broker y «can-i-deploy»

Con los contratos generándose en un pipeline y verificándose en otro, aparece un problema de información: «los números de versión de todas las aplicaciones que se probaron juntas, y si las pruebas pasaron o fallaron» quedan repartidos entre muchas ejecuciones de CI.

El **Pact Broker** es «una aplicación para compartir contratos dirigidos por el consumidor y resultados de verificación». Reúne esos datos y permite **determinar qué versiones de tus aplicaciones se pueden desplegar juntas de forma segura**.

Su consecuencia más útil es un comando:

```bash
# Antes de desplegar, preguntar si esta versión es compatible
pact-broker can-i-deploy \
  --pacticipant NOMBRE_DEL_PROVEEDOR \
  --version VERSION_DEL_PROVEEDOR
```

Lo usan los dos lados: el proveedor antes de desplegar, para confirmar compatibilidad con los consumidores que ya están en el ambiente; y el consumidor antes de liberar su cambio. Es la diferencia entre desplegar con información y desplegar con esperanza.

El broker además **versiona los contratos automáticamente** y maneja *etiquetas* y *ramas*, que permiten marcar qué versión está en cada ambiente y comprobar compatibilidad hacia atrás entre varias versiones de consumidores y proveedores.

## Contract testing y OpenAPI

Es la pregunta que aparece siempre, y no son alternativas: resuelven cosas distintas.

| | Especificación (OpenAPI) | Pacto |
|---|---|---|
| Qué describe | Todo lo que la API ofrece | Solo lo que un consumidor concreto usa |
| Quién lo escribe | El proveedor | Se genera con los tests del consumidor |
| Cómo se mantiene | A mano; se desactualiza | Se regenera al correr los tests |
| Responde «¿puedo cambiar esto?» | No: no sabe quién usa qué | Sí, con nombres de consumidores |
| Sirve como documentación pública | Sí, es su fuerte | No: es una herramienta de verificación |

Lo habitual y sensato es tener las dos: la especificación como documentación y contrato de diseño, y los pactos como red de seguridad de lo que efectivamente se consume.

## Qué no cubre

Prometer más de esto es la forma más común de que la iniciativa se abandone a los tres meses:

- **No verifica la lógica de negocio.** Comprueba que la respuesta tenga un campo `total` numérico, no que el total esté bien calculado. Eso son pruebas unitarias y funcionales.
- **No verifica que los datos sean correctos.** Solo su forma y sus tipos.
- **No reemplaza todas las pruebas de punta a punta.** Reemplaza a las que solo comprobaban que dos servicios se entendieran; conviene conservar unas pocas para los flujos críticos completos.
- **No cubre rendimiento ni carga.** Para eso, [pruebas de rendimiento con k6 y Grafana](../pruebas-de-rendimiento-con-k6-y-grafana/index.md).
- **No sirve para APIs de terceros que no controlás.** Nadie va a correr tu verificación en el pipeline de un proveedor externo. Ahí lo que sirve son pruebas de contrato contra su especificación y monitoreo.
- **Tiene costo de adopción.** Los *provider states* y la integración con CI llevan trabajo real. En un sistema con dos servicios, probablemente no valga la pena.

## Errores frecuentes

- **Escribir el pacto desde el proveedor.** Pierde todo el sentido: vuelve a describir lo que se ofrece en lugar de lo que se usa.
- **Declarar en el pacto campos que no se usan.** Cada campo declarado es una restricción que el proveedor no va a poder cambiar. Declarar solo lo que consumís.
- **Usar valores exactos donde alcanza el tipo.** Si tu código solo necesita que `id` sea un número, declarar que vale exactamente 42 vuelve el contrato frágil sin ganar nada.
- **Verificar contra un proveedor simulado.** La fase 2 pierde todo su valor si no corre contra el servicio real.
- **No publicar los pactos en un broker.** Sin broker no hay `can-i-deploy`, y se pierde el beneficio principal.
- **Prometer que reemplaza las pruebas de integración.** Genera una expectativa que no se cumple y desprestigia la práctica.
- **Adoptarlo en un sistema con dos servicios.** El costo de configuración no se recupera; conviene cuando hay varios equipos desplegando por separado.

## Preguntas frecuentes

### ¿Qué es el contract testing en una frase?

Según la documentación de Pact, es una técnica para probar un punto de integración revisando cada aplicación por separado, para asegurar que los mensajes que envía o recibe cumplen con un entendimiento compartido documentado en un contrato. La palabra clave es «por separado»: en lugar de levantar los dos servicios juntos, cada uno se verifica contra el contrato en su propio pipeline. Eso es lo que lo hace rápido y lo que permite saber cuál de los dos lados incumplió cuando algo falla.

### ¿Cuál es la diferencia con usar OpenAPI o Swagger?

Una especificación describe todo lo que la API ofrece; un pacto describe solo lo que un consumidor concreto realmente usa. Esa diferencia tiene una consecuencia práctica enorme: con una especificación no sabés si podés cambiar un campo, porque no sabés quién lo usa. Con contract testing sí, porque cada consumidor documentó lo que consume. Además, Pact es contrato por ejemplo y se genera ejecutando los tests reales del consumidor, así que no puede quedar desactualizado respecto del código como sí le pasa a un documento escrito a mano.

### ¿Por qué se dice que el contrato lo dirige el consumidor?

Porque el contrato no lo escribe quien publica la API sino quien la usa, y se genera durante la ejecución de los tests automatizados del consumidor. La lógica es que quien consume es el único que sabe qué campos necesita de verdad. El resultado es un contrato mínimo y honesto: contiene exactamente lo que se usa, ni más ni menos. Eso le da al proveedor la información que más le falta cuando quiere cambiar algo: quién depende de qué.

### ¿Rompe el contrato si el proveedor agrega un campo nuevo?

No, y ese es uno de los aciertos del diseño. La verificación pasa si cada petición genera una respuesta que contiene al menos los datos descritos en la respuesta mínima esperada por el consumidor. Agregar campos nuevos no rompe nada, porque el consumidor no declaró que la respuesta debía tener solo esos campos. Lo que sí rompe el contrato es quitar o renombrar un campo que algún consumidor declaró usar, cambiar su tipo, o cambiar el código de estado. Es exactamente el conjunto de cambios que en producción rompería a alguien.

### ¿Para qué sirve el broker y el can-i-deploy?

El broker es una aplicación para compartir los contratos y los resultados de verificación. Resuelve un problema real: sin él, la información de qué versiones se probaron juntas y si pasaron queda repartida entre muchas ejecuciones de CI. El comando can-i-deploy es la consecuencia útil: antes de desplegar, preguntás si esa versión concreta es compatible con las versiones que ya están en el ambiente de destino, y el broker responde con los datos que tiene. Es la diferencia entre desplegar con información y desplegar con esperanza.

### ¿Reemplaza a las pruebas de integración?

No, y prometer eso es la forma más rápida de que la iniciativa fracase. El contract testing verifica la forma del intercambio: rutas, códigos de estado, estructura y tipos de los datos. No verifica la lógica de negocio, ni que los datos sean correctos, ni el rendimiento, ni que el flujo completo tenga sentido de punta a punta. Lo que hace bien es reemplazar la mayor parte de las pruebas de integración lentas que solo comprobaban que los servicios se entendieran, y dejar unas pocas pruebas de punta a punta para los flujos críticos.

## Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 27 de julio de 2026.

### Aportes de la comunidad Underc0de

1. **Underc0de, foro.** [El mundo de las pruebas de API](https://underc0de.org/foro/qa-testing/el-mundo-de-las-pruebas-de-api/), sección QA y Testing, 23 de julio de 2024.
2. **Underc0de, foro.** [Testeo de APIs con Postman](https://underc0de.org/foro/qa-testing/testeo-de-apis-con-postman/), por *ANTRAX*, 3 de octubre de 2021.
3. **Underc0de, foro.** [Corriendo colecciones de APIs con Newman y reporte en HTML](https://underc0de.org/foro/qa-testing/corriendo-colecciones-de-apis-con-newman-y-reporte-en-html/), por *ANTRAX*, 22 de marzo de 2022.

### Documentación oficial

4. **Pact.** [Documentación oficial](https://docs.pact.io/). Definición de contract testing, roles de consumidor y proveedor, enfoque dirigido por el consumidor y «contrato por ejemplo», citados textualmente.
5. **Pact.** [How Pact works](https://docs.pact.io/getting_started/how_pact_works). Los cuatro pasos de la fase del consumidor, la generación del archivo de pacto y la verificación contra la respuesta mínima esperada.
6. **Pact.** [Pact Broker](https://docs.pact.io/pact_broker). Qué es el broker, el problema de información que resuelve, el comando `can-i-deploy` y el manejo de versiones, etiquetas y ramas.

---

Esta guía forma parte de un proyecto de la comunidad Underc0de para organizar conocimiento técnico en español. Fuente canónica: https://underc0de.org/guias/testing/contract-testing-de-apis-con-pact/
