O que Todo Dev Deve Saber sobre Contract Testing com Pact: Garantindo Compatibilidade entre Serviços Já leu

O Que é Contract Testing com Pact? Contract Testing é uma metodologia que valida a comunicação entre serviços (consumidor e provedor) sem depender de ambientes integrados completos. O Pact é um framework open-source que implementa essa abordagem de forma elegante, permitindo que cada serviço defina contratos — acordos sobre como devem se comunicar. Ao invés de testes de integração pesados, você cria "contratos" que garantem compatibilidade mútua, detectando quebras de contrato antes de chegarem à produção. A grande vantagem? Equipes podem trabalhar independentemente. O consumidor define o que espera do provedor, e o provedor valida se consegue entregar. Não é necessário que ambos os serviços estejam rodando simultaneamente durante os testes. Isso acelera o ciclo de desenvolvimento e reduz custos de infraestrutura de testes. Entendendo os Componentes Principais Consumer-Driven Contracts No Pact, o consumidor define primeiro o contrato. Ele escreve testes especificando exatamente como vai chamar o provedor: qual endpoint, que parâmetros envia, que resposta espera. O consumidor não fica

O Que é Contract Testing com Pact?

Contract Testing é uma metodologia que valida a comunicação entre serviços (consumidor e provedor) sem depender de ambientes integrados completos. O Pact é um framework open-source que implementa essa abordagem de forma elegante, permitindo que cada serviço defina contratos — acordos sobre como devem se comunicar. Ao invés de testes de integração pesados, você cria "contratos" que garantem compatibilidade mútua, detectando quebras de contrato antes de chegarem à produção.

A grande vantagem? Equipes podem trabalhar independentemente. O consumidor define o que espera do provedor, e o provedor valida se consegue entregar. Não é necessário que ambos os serviços estejam rodando simultaneamente durante os testes. Isso acelera o ciclo de desenvolvimento e reduz custos de infraestrutura de testes.

Entendendo os Componentes Principais

Consumer-Driven Contracts

No Pact, o consumidor define primeiro o contrato. Ele escreve testes especificando exatamente como vai chamar o provedor: qual endpoint, que parâmetros envia, que resposta espera. O consumidor não fica preso à implementação real do provedor — apenas ao contrato acordado. Esse arquivo de contrato é compartilhado com o provedor, que valida se consegue cumprir as promessas.

O Arquivo de Contrato (JSON)

O Pact gera automaticamente um arquivo JSON documentando o contrato. Este arquivo contém todas as interações esperadas entre consumidor e provedor. É um documento vivo que evolui com o tempo, funcionando simultaneamente como teste e documentação.

{
  "consumer": {
    "name": "UserService"
  },
  "provider": {
    "name": "AuthService"
  },
  "interactions": [
    {
      "description": "Validar token do usuário",
      "request": {
        "method": "POST",
        "path": "/auth/validate",
        "body": {
          "token": "abc123"
        }
      },
      "response": {
        "status": 200,
        "body": {
          "valid": true,
          "userId": "user-1"
        }
      }
    }
  ]
}

Implementação Prática com Pact (JavaScript/Node.js)

Escrevendo Testes do Consumidor

O consumidor começa definindo o que espera do provedor. Aqui, o UserService espera chamar o AuthService:

const { PactV3 } = require("@pact-foundation/pact");
const axios = require("axios");

const pact = new PactV3({
  consumer: "UserService",
  provider: "AuthService",
  port: 9876,
});

describe("AuthService Contract", () => {
  it("deve validar token com sucesso", async () => {
    pact.addInteraction({
      states: ["token válido existe"],
      uponReceiving: "validação de token",
      withRequest: {
        method: "POST",
        path: "/auth/validate",
        body: { token: "abc123" },
        headers: { "Content-Type": "application/json" },
      },
      willRespondWith: {
        status: 200,
        body: { valid: true, userId: "user-1" },
      },
    });

    await pact.executeTest(async (mockServer) => {
      const response = await axios.post(
        `${mockServer.url}/auth/validate`,
        { token: "abc123" }
      );
      expect(response.data.valid).toBe(true);
      expect(response.data.userId).toBe("user-1");
    });
  });
});

Validando o Contrato no Provedor

O AuthService agora valida se consegue cumprir o contrato. O Pact fornece um arquivo gerado no consumidor que o provedor testa contra sua implementação real:

const { Verifier } = require("@pact-foundation/pact");
const app = require("./app"); // Sua aplicação Express

describe("AuthService Pact Verification", () => {
  it("honra o contrato com UserService", async () => {
    const verificationOptions = {
      provider: "AuthService",
      providerBaseUrl: "http://localhost:3000",
      pactFiles: [
        "./pacts/UserService-AuthService.json",
      ],
      stateHandlers: {
        "token válido existe": async () => {
          // Preparar estado: inserir token no banco de dados
          await db.tokens.create({ value: "abc123", userId: "user-1" });
        },
      },
    };

    return new Verifier(verificationOptions).verifyProvider();
  });
});

Fluxo de Trabalho Completo

O processo segue um ciclo bem definido: (1) Consumidor escreve testes, (2) Pact gera arquivo de contrato, (3) Provedor executa verificação, (4) Se falhar, provedor ajusta sua API, (5) Se passar, integração é segura. Contratos são compartilhados via repositório ou Pact Broker (servidor centralizado que gerencia contratos e pode disparar deploys automaticamente).

Para ambientes corporativos, o Pact Broker é essencial. Ele centraliza contratos, permite que qualquer serviço consulte o que é esperado dele, e integra-se com pipelines CI/CD. Quando um contrato quebra, o Broker notifica automaticamente qual serviço está incompatível com qual outro.

# Publicar contrato no Pact Broker
pact-broker publish ./pacts \
  --consumer-app-version=1.0.0 \
  --broker-base-url=https://pact-broker.company.com \
  --broker-token=$PACT_BROKER_TOKEN

# Verificar compatibilidade antes de fazer deploy
pact-broker can-i-deploy \
  --pacticipant=AuthService \
  --version=1.0.0 \
  --broker-base-url=https://pact-broker.company.com

Conclusão

Contract Testing com Pact resolve um problema real: como garantir compatibilidade entre serviços distribuídos sem testes de integração lentos e frágeis. Você aprendeu que (1) contratos são documentos acordados entre consumidor e provedor, não imposições unilaterais, (2) o framework gera automaticamente provas de compatibilidade que podem ser reutilizadas em CI/CD, e (3) escalabilidade cresce com ferramentas como Pact Broker, não com complexidade dos testes. Implemente Pact em um microsserviço hoje e veja a qualidade dos seus deploys aumentar.

Referências


Artigos relacionados