DEV Community

Cover image for Como Mockar uma API para Testes: Guia Prático
Lucas
Lucas

Posted on • Originally published at apidog.com

Como Mockar uma API para Testes: Guia Prático

Testes que dependem de uma API ativa falham pelos motivos errados: servidor de homologação fora do ar, rate limit de terceiros, dados alterados por outra pessoa ou instabilidade de rede. Para testar o seu código com previsibilidade, substitua o endpoint real por um mock controlado que retorna a resposta esperada sempre que o teste roda.

Experimente o Apidog hoje

Neste guia, você vai montar um fluxo prático para simular uma API em testes: definir um esquema, gerar respostas mock, executar um servidor mock, apontar sua suíte para ele e cobrir cenários de erro. Os exemplos usam uma API simples de pedidos com GET /orders/{id}, mas o mesmo padrão funciona para REST ou GraphQL.

Quando simular a API é a escolha certa

Use mocks quando o objetivo do teste for validar o comportamento do seu código, não a disponibilidade da rede ou do backend.

Bons casos para mock:

  • Testes de unidade de clients HTTP.
  • Testes de integração entre módulos internos.
  • Validação de tratamento de erros.
  • Testes de timeout, retry e fallback.
  • Desenvolvimento frontend antes do backend estar pronto.

Exemplo: você quer verificar se seu client interpreta um 200, trata um 404 com uma mensagem clara e tenta novamente após um 503. Nenhum desses casos exige um servidor real.

Mantenha a API real para uma camada menor de testes:

  • Testes de contrato.
  • Smoke tests.
  • Testes ponta a ponta críticos.

A divisão prática é: use mock para velocidade e isolamento; use o serviço real para confirmar que o contrato continua válido. Para aprofundar, veja estes cenários onde a simulação de API compensa e a diferença entre servidor mock e servidor real.

Fluxo de trabalho em 5 passos

Simular uma API para testes normalmente segue este fluxo:

  1. Defina o esquema da API.
  2. Crie respostas simuladas, estáticas ou dinâmicas.
  3. Execute um servidor mock local ou hospedado.
  4. Configure seus testes para usar a URL do mock.
  5. Teste caminhos de erro difíceis de reproduzir em produção.

Vamos aplicar isso ao endpoint:

GET /orders/{id}
Enter fullscreen mode Exit fullscreen mode

Passo 1: Defina o esquema

Um mock só é útil se representar o contrato real da API. Comece por um esquema. Se sua API já tem um documento OpenAPI, use-o. Caso contrário, escreva uma especificação mínima para o endpoint que será testado.

Exemplo simplificado:

paths:
  /orders/{id}:
    get:
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: string }
                  status: { type: string, enum: [pending, shipped, delivered] }
                  total: { type: number }
                  items: { type: array, items: { type: object } }
        '404':
          description: Order not found
Enter fullscreen mode Exit fullscreen mode

Esse esquema serve para duas coisas:

  • Define quais campos o mock deve retornar.
  • Centraliza o contrato entre backend, frontend e testes.

Quando o backend altera o contrato, você atualiza o esquema e regenera os mocks a partir dele. Essa é a base para manter o teste de contrato de API confiável.

Passo 2: Gere respostas simuladas

Você pode trabalhar com dois tipos de resposta mock.

Respostas estáticas

São payloads JSON fixos. O mock sempre retorna o mesmo conteúdo.

Exemplo:

{
  "id": "order_8842",
  "status": "shipped",
  "total": 149.99,
  "items": [
    {
      "sku": "sku_123",
      "quantity": 1
    },
    {
      "sku": "sku_456",
      "quantity": 2
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Use respostas estáticas quando o teste precisa de asserções previsíveis:

expect(order.id).toBe('order_8842');
expect(order.status).toBe('shipped');
expect(order.total).toBe(149.99);
Enter fullscreen mode Exit fullscreen mode

Respostas dinâmicas

São geradas a cada requisição. Em vez de fixar "total": 149.99, o mock pode gerar valores realistas com base no esquema:

  • UUID para id.
  • Valor do enum para status.
  • Número plausível para total.
  • Lista variável para items.

Esse tipo de resposta ajuda a encontrar bugs que um único payload fixo pode esconder, como:

  • Parser quebrando com strings longas.
  • Campos opcionais ausentes.
  • Valores nulos.
  • Arrays vazios.
  • Valores numéricos fora do comum.

Na prática, use os dois:

  • Payloads estáticos para testes com muitas asserções.
  • Payloads dinâmicos para ampliar cobertura.

Com Apidog, você pode gerar endpoints mock diretamente a partir do esquema. A ferramenta identifica nomes de campos como email, phone ou avatar e preenche valores compatíveis automaticamente.

Ao escrever payloads manualmente, evite dados irreais. Um pedido com "total": 0 e items: [] pode passar no teste, mas não representa bem uma resposta de produção. Prefira dados próximos dos reais: total plausível, múltiplos itens e status válido no enum.

Passo 3: Execute o servidor mock

Depois de definir as respostas, você precisa servi-las em uma URL.

Você tem duas opções principais.

Opção 1: servidor mock local

Um servidor local roda na sua máquina, normalmente em uma porta como localhost:4010.

Use essa opção para:

  • Testes de unidade.
  • Testes de integração.
  • Execuções locais.
  • Pipelines de CI com ambiente controlado.

Com o Prism, por exemplo, você pode iniciar um mock a partir de um arquivo OpenAPI:

prism mock openapi.yaml
# Mock server listening on http://127.0.0.1:4010
Enter fullscreen mode Exit fullscreen mode

Depois disso, qualquer chamada para:

GET http://127.0.0.1:4010/orders/order_8842
Enter fullscreen mode Exit fullscreen mode

retorna uma resposta compatível com o contrato.

Opção 2: servidor mock na nuvem

Um servidor mock na nuvem fornece uma URL pública.

Use essa opção quando:

  • Um app mobile precisa acessar o mock.
  • Um colaborador externo precisa testar a API.
  • Um runner de CI não consegue acessar sua máquina.
  • Você quer compartilhar um endpoint mock com outra equipe.

O Apidog fornece uma URL de Cloud Mock por projeto, permitindo que outras pessoas chamem o mesmo endpoint sem depender do seu ambiente local.

Para testes automatizados, prefira o mock local. Ele evita latência externa, reduz flakiness e elimina estado compartilhado entre builds. Use o mock na nuvem para demonstrações, testes entre dispositivos e colaboração.

Passo 4: Aponte seus testes para o mock

Não deixe a URL da API fixa no código. Torne a URL base configurável por variável de ambiente.

Exemplo em JavaScript:

// orderClient.test.js
import { getOrder } from './orderClient.js';

const BASE_URL = process.env.API_BASE_URL || 'http://127.0.0.1:4010';

test('parses a shipped order', async () => {
  const order = await getOrder('order_8842', BASE_URL);

  expect(order.status).toBe('shipped');
  expect(typeof order.total).toBe('number');
});
Enter fullscreen mode Exit fullscreen mode

O client recebe a URL base como argumento:

// orderClient.js
export async function getOrder(id, baseUrl) {
  const response = await fetch(`${baseUrl}/orders/${id}`);

  if (!response.ok) {
    throw new Error(`Failed to fetch order: ${response.status}`);
  }

  return response.json();
}
Enter fullscreen mode Exit fullscreen mode

Assim, o mesmo teste pode rodar contra ambientes diferentes:

# Local usando mock
API_BASE_URL=http://127.0.0.1:4010 npm test

# Job separado usando API real para contrato
API_BASE_URL=https://api.example.com npm test
Enter fullscreen mode Exit fullscreen mode

Esse padrão mantém a simulação fora da lógica da aplicação. Se você executa testes em pipeline, aplique a mesma ideia ao automatizar testes de API em CI/CD.

Passo 5: Teste os caminhos de erro

Esse é o ponto em que mocks mais ajudam. Um servidor real raramente retorna um 500 exatamente quando você precisa testar seu fallback. Um mock retorna sob demanda.

Configure respostas específicas para falhas e valide o comportamento do client.

Cenário Mock retorna O que verificar
Registro ausente 404 Client lança erro claro de "não encontrado"
Falha no servidor 500 Client tenta novamente e depois exibe fallback
Limite de taxa atingido 429 com Retry-After Client aguarda o tempo correto
Resposta lenta 200 após 5s de atraso Client atinge timeout e se recupera
Corpo malformado 200 com JSON quebrado Client falha graciosamente, sem travar

Exemplo de teste para 404:

test('throws clear error when order is not found', async () => {
  await expect(getOrder('order_404', BASE_URL)).rejects.toThrow(
    'Failed to fetch order: 404'
  );
});
Enter fullscreen mode Exit fullscreen mode

Exemplo de teste para retry em 500:

test('retries when server returns 500', async () => {
  const order = await getOrderWithRetry('order_retry', BASE_URL, {
    retries: 2
  });

  expect(order.status).toBe('shipped');
});
Enter fullscreen mode Exit fullscreen mode

As regras avançadas de mock do Apidog permitem retornar respostas diferentes com base na requisição. Por exemplo:

  • GET /orders/order_404 retorna 404.
  • GET /orders/order_timeout retorna 200 com atraso.
  • Qualquer outro ID retorna 200.

Isso permite cobrir caminho feliz e falhas usando o mesmo endpoint mock. Combine com assertivas de API para verificar comportamento, não apenas status code.

Organizando mocks em uma suíte de testes crescente

Um endpoint mock é fácil de manter. Cem endpoints espalhados pela suíte viram dívida técnica rapidamente.

Use estas práticas:

Agrupe mocks por serviço

Organize os mocks pelo serviço real que representam, não pelo teste que os consome.

Exemplo:

tests/
  mocks/
    orders/
      order-shipped.json
      order-not-found.json
      order-rate-limited.json
    payments/
      payment-approved.json
      payment-declined.json
Enter fullscreen mode Exit fullscreen mode

Quando a API de pedidos muda, você sabe onde atualizar.

Nomeie fixtures pelo cenário

Prefira nomes que expliquem o comportamento:

order-shipped.json
order-pending.json
order-404.json
order-rate-limited.json
Enter fullscreen mode Exit fullscreen mode

Evite nomes genéricos como:

response1.json
mock-data.json
test.json
Enter fullscreen mode Exit fullscreen mode

Um teste falhando com order-rate-limited é muito mais fácil de diagnosticar.

Versione mocks junto com os testes

Mocks fazem parte da suíte. Eles devem passar por code review como qualquer outro código de teste.

Inclua no PR:

  • Alteração no esquema.
  • Alteração no mock.
  • Alteração nos testes afetados.

Reutilize uma resposta base

Evite criar payloads completamente diferentes para cada teste. A maioria dos cenários muda apenas um campo.

Exemplo:

const baseOrder = {
  id: 'order_8842',
  status: 'shipped',
  total: 149.99,
  items: [
    { sku: 'sku_123', quantity: 1 },
    { sku: 'sku_456', quantity: 2 }
  ]
};

const pendingOrder = {
  ...baseOrder,
  status: 'pending'
};

const deliveredOrder = {
  ...baseOrder,
  status: 'delivered'
};
Enter fullscreen mode Exit fullscreen mode

Isso reduz duplicação e facilita mudanças no contrato. A mesma disciplina usada em uma suíte de testes para automação de API também vale para mocks.

Mantendo o mock honesto

Mocks podem se desviar da API real.

Exemplos comuns:

  • Backend adiciona um campo obrigatório.
  • total vira amount.
  • Um enum recebe novo valor.
  • Um campo deixa de ser string e vira number.
  • A estrutura de erro muda.

Se seus testes rodam apenas contra o mock antigo, eles continuam verdes enquanto a produção quebra.

Para evitar isso, adote dois hábitos.

1. Gere o mock a partir do mesmo esquema do backend

Se o backend publica OpenAPI, use esse arquivo como fonte única da verdade.

Fluxo recomendado:

OpenAPI schema
      ↓
Mock server
      ↓
Testes de unidade/integração
Enter fullscreen mode Exit fullscreen mode

Quando o esquema muda, o mock muda junto. Um mock escrito manualmente tende a ficar desatualizado.

2. Rode testes de contrato contra a API real

Mantenha um conjunto pequeno de testes que valida a API real contra o esquema.

Esse job pode rodar:

  • A cada merge.
  • Em horário agendado.
  • Antes de releases.
  • Contra staging.

O objetivo não é testar toda a aplicação de novo. O objetivo é responder: "a API real ainda corresponde ao contrato usado pelos mocks?"

Se esse teste falhar, atualize o esquema e regenere os mocks antes que a quebra chegue aos usuários.

Também revise mocks durante code review. Se um PR altera uma resposta da API, o mock correspondente deve mudar junto. Trate o mock como parte do contrato, não como um detalhe descartável de teste.

Se você quer um ambiente único para manter esquema, mock server e testes sincronizados, baixe o Apidog. Para comparar alternativas, veja este resumo de ferramentas de simulação de API REST.

Perguntas frequentes

Devo simular a API para todos os testes?

Não. Simule em testes de unidade e integração quando o foco for validar o seu código. Mantenha um conjunto menor de testes de contrato e ponta a ponta contra a API real para confirmar que o mock ainda corresponde à produção.

Qual é a diferença entre resposta mock estática e dinâmica?

Uma resposta estática é um JSON fixo, ideal para asserções previsíveis. Uma resposta dinâmica é gerada por requisição com valores realistas, útil para encontrar bugs que um único payload fixo não cobre. Na prática, use ambas.

Como garanto que meu mock permaneça preciso?

Gere o mock a partir do mesmo esquema usado pelo backend, preferencialmente OpenAPI. Depois, execute testes de contrato contra a API real para confirmar que as respostas em produção ou staging ainda seguem esse esquema.

Um mock pode simular respostas lentas ou com falha?

Sim. Você pode configurar um mock para retornar 500, 429 com cabeçalho Retry-After, JSON inválido ou uma resposta 200 com atraso. Isso permite testar retry, timeout e fallback de forma controlada.

Servidor mock local ou servidor mock na nuvem para testes?

Use servidor mock local para execuções automatizadas. Ele é mais rápido, evita latência de rede e reduz flakiness. Use mock na nuvem quando um dispositivo móvel, runner de CI ou colaborador externo precisar acessar o endpoint sem depender da sua máquina.

Top comments (0)