Como mockar CEP no Cypress com dados brasileiros falsos
Como mockar CEP no Cypress com dados brasileiros falsos
Testes E2E que dependem de APIs externas quebram. Não é hipótese — é certeza estatística. Se o seu fluxo de checkout, cadastro ou validação de endereço faz uma chamada real para ViaCEP ou BrasilAPI durante o Cypress, você está transferindo a responsabilidade de estabilidade do seu pipeline para um servidor que você não controla. Este guia resolve isso: você vai interceptar essas chamadas, substituí-las por dados brasileiros falsos e coerentes, e manter seus testes verdes independente de qualquer dependência externa.
---
O problema real: testes E2E quebrando por dependência de CEP externo
Por que consultar ViaCEP ou BrasilAPI nos testes é arriscado
ViaCEP e BrasilAPI são excelentes para produção. Para testes, são fontes de flakiness. O problema não é a qualidade dos serviços — é a natureza do teste E2E: você precisa de controle total sobre os dados de entrada e saída. Quando o CEP digitado no teste retorna dados diferentes dependendo do dia (endereço atualizado, bairro renomeado, CEP descontinuado), suas assertions falham por motivos que não têm nada a ver com o código que você está testando.
Flakiness causada por rate limit, timeout e dados inconsistentes
A BrasilAPI aplica rate limiting. Em pipelines de CI com múltiplos workers rodando testes em paralelo, você vai atingir esse limite. O resultado: requisições com status 429 ou timeout, campos de endereço vazios no DOM, assertions falhando com mensagens que parecem bugs da aplicação mas são só throttling de API. Além disso, CEPs reais mudam. O Correios atualiza sua base regularmente — um CEP que existia ontem pode retornar objeto vazio amanhã.
O que significa "mockar" uma API no contexto do Cypress
Mockar no Cypress significa interceptar uma requisição HTTP antes que ela saia do browser e devolver uma resposta controlada. O cy.intercept() age como um proxy no nível do Service Worker do browser de teste: a requisição é capturada, a resposta que você definiu é retornada, e a aplicação nunca chega a tocar a rede real. Para o código da aplicação, a chamada foi feita normalmente.
---
Anatomia de um endereço brasileiro válido para testes
Campos obrigatórios: logradouro, bairro, localidade, UF, CEP
O formato ViaCEP retorna oito campos. Para testes funcionais, os cinco que importam são:
| Campo | Exemplo | Usado em |
|---|---|---|
logradouro | Rua das Palmeiras | Input de rua |
bairro | Vila Madalena | Input de bairro |
localidade | São Paulo | Input de cidade |
uf | SP | Select de estado |
cep | 01310-100 | Input de CEP |
Os demais (ibge, gia, ddd, siafi) raramente afetam lógica de formulário, mas alguns sistemas usam o ddd para pré-preencher telefone.
Correlação entre prefixo do CEP e estado (ex: 01xxx–09xxx = SP)
CEPs brasileiros seguem faixas por estado definidas pelos Correios. São Paulo ocupa 01000-000 a 09999-999. Rio de Janeiro vai de 20000-000 a 28999-999. Um endereço com cep: "01310-100" e uf: "RJ" é geograficamente impossível — e se a sua aplicação valida isso (muitas validam frete, filial regional, ICMS), o teste vai falhar com um falso negativo.
Por que dados aleatórios sem correlação geram falsos negativos nos testes
Gerar CEP e UF de forma independente cria combinações inválidas. A aplicação rejeita o endereço, o teste falha, o dev investiga achando que é bug, descobre que é fixture corrompida, perde tempo. Dados correlacionados — onde CEP, bairro, cidade e UF pertencem à mesma região — eliminam essa categoria de problema.
---
Gerando endereços brasileiros falsos e coerentes
Usando o gerador de CEP do FakeForge BR via interface web
O gerador de CEP do FakeForge BR gera endereços completos com correlação garantida entre todos os campos. Para testes pontuais, você pode gerar manualmente, copiar o JSON e salvar como fixture. Para uso em pipeline, a API é mais adequada.
Consumindo a API REST do FakeForge BR para gerar lotes de endereços
curl "https://fakeforge.com.br/api/generate?type=cep&quantity=5&format=json"A API REST do FakeForge BR aceita type, quantity (máx 10.000) e format (json, csv, sql). O plano gratuito cobre 100 chamadas/dia — suficiente para a maioria dos pipelines de CI.
Estrutura do payload retornado e mapeamento para o formato ViaCEP
O FakeForge retorna o seguinte formato por item:
{
"cep": "04538-132",
"logradouro": "Avenida Brigadeiro Faria Lima",
"bairro": "Itaim Bibi",
"localidade": "São Paulo",
"uf": "SP",
"ddd": "11"
}Isso é idêntico ao formato ViaCEP. Você pode usar o payload diretamente como resposta do intercept sem transformação.
---
Configurando cy.intercept() para substituir a chamada de CEP
Sintaxe básica do cy.intercept com fixture estática
// cypress/e2e/cadastro.cy.ts
describe('Preenchimento automático de endereço', () => {
beforeEach(() => {
cy.intercept('GET', '**/viacep.com.br/ws/**', {
fixture: 'endereco-sp.json',
}).as('buscarCep');
});
it('preenche os campos após digitar CEP', () => {
cy.visit('/cadastro');
cy.get('[data-testid="input-cep"]').type('01310100');
cy.wait('@buscarCep');
cy.get('[data-testid="input-logradouro"]').should('have.value', 'Avenida Paulista');
});
});Interceptando padrões de URL (glob e regex para qualquer CEP digitado)
O glob /viacep.com.br/ws/ captura qualquer CEP. Se a aplicação usa BrasilAPI, ajuste:
// Intercepta qualquer CEP na BrasilAPI
cy.intercept('GET', '**/brasilapi.com.br/api/cep/v1/**', {
fixture: 'endereco-sp.json',
}).as('buscarCep');
// Ou com regex para cobrir ambas
cy.intercept('GET', /viacep\.com\.br|brasilapi\.com\.br/, {
fixture: 'endereco-sp.json',
}).as('buscarCep');Respondendo com objeto inline vs fixture salva em cypress/fixtures
Fixture salva é melhor para dados fixos reutilizados. Objeto inline é melhor para dados dinâmicos gerados no beforeEach:
// Objeto inline — útil quando o endereço varia por teste
cy.intercept('GET', '**/viacep.com.br/ws/**', {
statusCode: 200,
body: {
cep: '04538-132',
logradouro: 'Avenida Brigadeiro Faria Lima',
bairro: 'Itaim Bibi',
localidade: 'São Paulo',
uf: 'SP',
ddd: '11',
},
}).as('buscarCep');---
Fixture dinâmica: gerando endereços falsos no beforeEach
Criando um comando customizado generateFakeAddress
// cypress/support/commands.ts
Cypress.Commands.add('generateFakeAddress', () => {
return cy.task('gerarEndereco');
});
declare global {
namespace Cypress {
interface Chainable {
generateFakeAddress(): Chainable<ViaCepResponse>;
}
}
}Chamando a API FakeForge BR dentro do cy.task
// cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
setupNodeEvents(on) {
on('task', {
async gerarEndereco() {
const res = await fetch(
'https://fakeforge.com.br/api/generate?type=cep&quantity=1&format=json'
);
const data = await res.json();
// A API retorna array — pegar o primeiro item
return data[0];
},
});
},
},
});DICA: Ocy.taskroda no processo Node do Cypress (fora do browser), então chamadasfetchnativas funcionam no Node 18+. Para Node 16, substitua porhttps.getou instalenode-fetch.
Vinculando o endereço gerado ao alias e reutilizando nos assertions
// cypress/e2e/cadastro.cy.ts
describe('Endereço dinâmico', () => {
beforeEach(() => {
cy.task('gerarEndereco').then((endereco) => {
cy.wrap(endereco).as('enderecoFalso');
cy.intercept('GET', '**/viacep.com.br/ws/**', {
statusCode: 200,
body: endereco,
}).as('buscarCep');
});
});
it('verifica campos preenchidos com dados correlacionados', function () {
// Usar function() para acessar this.enderecoFalso
cy.visit('/cadastro');
cy.get('[data-testid="input-cep"]').type(
this.enderecoFalso.cep.replace('-', '')
);
cy.wait('@buscarCep');
cy.get('[data-testid="input-logradouro"]').should(
'have.value',
this.enderecoFalso.logradouro
);
cy.get('[data-testid="input-uf"]').should('have.value', this.enderecoFalso.uf);
});
});---
Testando o fluxo completo de preenchimento automático de endereço
Digitando o CEP no input e verificando o preenchimento dos campos
it('preenche logradouro, bairro, cidade e UF automaticamente', function () {
cy.visit('/checkout/endereco');
cy.get('[data-testid="input-cep"]').type(
this.enderecoFalso.cep.replace('-', '')
);
cy.wait('@buscarCep');
cy.get('[data-testid="input-logradouro"]').should(
'have.value',
this.enderecoFalso.logradouro
);
cy.get('[data-testid="input-bairro"]').should(
'have.value',
this.enderecoFalso.bairro
);
cy.get('[data-testid="input-cidade"]').should(
'have.value',
this.enderecoFalso.localidade
);
cy.get('[data-testid="select-uf"]').should('have.value', this.enderecoFalso.uf);
});Cobrindo o caso de CEP inválido (mock de erro 404 / objeto vazio)
ViaCEP retorna { "erro": true } com status HTTP 200 para CEPs inexistentes — não um 404. Sua aplicação precisa tratar isso, e seu teste precisa cobrir:
it('exibe mensagem de erro para CEP inválido', () => {
cy.intercept('GET', '**/viacep.com.br/ws/**', {
statusCode: 200,
body: { erro: true },
}).as('buscarCepInvalido');
cy.visit('/checkout/endereco');
cy.get('[data-testid="input-cep"]').type('99999999');
cy.wait('@buscarCepInvalido');
cy.get('[data-testid="erro-cep"]').should('be.visible').and('contain', 'CEP não encontrado');
});AVISO: Não mocke CEP inválido como status 404. ViaCEP retorna 200 com{ erro: true }. Se sua aplicação checaresponse.okem vez do campoerro, este comportamento específico ficará sem cobertura de teste.
---
Isolando testes por estado ou região com diferentes fixtures
Estrutura de pastas para fixtures regionais
cypress/
fixtures/
enderecos/
endereco-sp.json
endereco-rj.json
endereco-rs.json
endereco-ba.jsonExemplo de cypress/fixtures/enderecos/endereco-sp.json:
{
"cep": "01310-100",
"logradouro": "Avenida Paulista",
"complemento": "de 1 a 610 - lado par",
"bairro": "Bela Vista",
"localidade": "São Paulo",
"uf": "SP",
"ddd": "11"
}Parametrizando testes com cy.each para múltiplos estados
const estados = ['sp', 'rj', 'rs', 'ba'];
estados.forEach((uf) => {
it(`calcula frete corretamente para ${uf.toUpperCase()}`, () => {
cy.intercept('GET', '**/viacep.com.br/ws/**', {
fixture: `enderecos/endereco-${uf}.json`,
}).as('buscarCep');
cy.visit('/frete');
cy.get('[data-testid="input-cep"]').type('01310100');
cy.wait('@buscarCep');
cy.get('[data-testid="valor-frete"]').should('be.visible');
});
});---
Boas práticas para não quebrar o ambiente de staging
Usando variável de ambiente para ativar mock apenas em CI
# .env.ci
CYPRESS_MOCK_CEP=true// cypress/e2e/cadastro.cy.ts
const mockCep = Cypress.env('MOCK_CEP') === 'true';
beforeEach(() => {
if (mockCep) {
cy.intercept('GET', '**/viacep.com.br/ws/**', {
fixture: 'enderecos/endereco-sp.json',
}).as('buscarCep');
}
});Não interceptar em testes de contrato ou smoke tests de integração real
Testes de contrato verificam se a API externa ainda retorna o formato esperado. Interceptar esses testes derrota o propósito. Separe por pasta ou tag:
// Teste de contrato — sem mock
it('ViaCEP retorna campos esperados', { tags: ['@contrato'] }, () => {
cy.request('GET', 'https://viacep.com.br/ws/01310100/json/').then((res) => {
expect(res.body).to.have.keys(['cep', 'logradouro', 'bairro', 'localidade', 'uf']);
});
});Documentando quais testes usam dados falsos vs dados reais
Adicione um comentário de cabeçalho nos arquivos de teste que usam mocks:
/**
* DADOS: mock via FakeForge BR (/api/generate?type=cep)
* Não roda chamadas reais para ViaCEP.
* Para testes de contrato, veja: cypress/e2e/contratos/viacep.cy.ts
*/---
LGPD e dados de endereço em testes
LGPD Art. 7º, IX e o risco de usar endereços reais de usuários em fixtures
A LGPD Art. 7º, IX permite tratamento de dados pessoais apenas quando há base legal. Usar endereços reais de usuários em fixtures de teste — mesmo anonimizados parcialmente — pode caracterizar tratamento sem consentimento e sem base legal adequada. O endereço completo de uma pessoa física é dado pessoal.
Por que dados gerados (não coletados) eliminam a obrigação de consentimento
Dados gerados sinteticamente nunca pertenceram a nenhuma pessoa física. Não há titular. Não há base legal necessária porque não existe dado pessoal. Um CEP falso gerado pelo FakeForge BR com logradouro, bairro e cidade correlacionados é tecnicamente válido para testes e juridicamente neutro para fins da LGPD.
Como o FakeForge BR garante que nenhum dado real é armazenado ou processado
O FakeForge BR não usa bases de dados de pessoas reais. Os geradores são algoritmos determinísticos: CPF via módulo 11, CNPJ via dígitos verificadores, endereços via tabelas de prefixos dos Correios sem consulta externa. Nenhuma requisição à API armazena os dados gerados. Não há log associado a usuário, não há PII em trânsito.
---
Resumo
- Intercepte sempre em E2E: Use
cy.intercept()para toda chamada de CEP externo — ViaCEP, BrasilAPI ou qualquer outra. Testes E2E não devem depender de disponibilidade de APIs de terceiros. - Dados correlacionados evitam falsos negativos: CEP, bairro, cidade e UF devem ser geograficamente coerentes. Use o gerador de CEP do FakeForge BR ou a API REST para garantir essa correlação.
cy.taskpara geração dinâmica: Chame a API FakeForge BR nocypress.config.tsviataskpara gerar endereços frescos por suite, evitando fixtures estáticas que ficam defasadas.- Trate
{ erro: true }com status 200: ViaCEP não retorna 404 para CEP inválido. Cubra este caso explicitamente no mock para garantir que o tratamento de erro da aplicação está coberto. - Ative mocks via variável de ambiente:
CYPRESS_MOCK_CEP=trueno CI e desligado em testes de contrato. Mantenha a separação documentada no cabeçalho dos arquivos de teste. - Dados gerados são LGPD-safe: Substitua qualquer fixture com endereço real de usuário por dados sintéticos. Para mockar validação de CPF no fluxo de cadastro, dados de empresa nos testes de formulário B2B ou chaves PIX em fluxos de pagamento, o mesmo princípio se aplica.
Perguntas frequentes
Como mockar duas requisições de CEP diferentes no mesmo teste (endereço de cobrança + entrega)?+
Use cy.intercept com callback para diferenciar por padrão de URL. Verifique o query param ou o caminho e retorne a fixture apropriada: cy.intercept('GET', '**/viacep.com.br/**', (req) => { req.reply((res) => { res.body = req.url.includes('01310') ? enderecoSP : enderecORJ; }); }).
O cy.task chamando a API FakeForge BR em cada teste fica lento em CI com paralelo?+
Sim. Para pipelines com 4+ workers, gere 50 endereços uma vez antes da suite e distribua via fixture JSON carregado de setup. Ou mova o cy.task para um arquivo pluginFile que roda antes de tudo, economizando requisições HTTP repetidas entre testes paralelos.
Como mockar timeout ou erro 504 da ViaCEP sem chamar de verdade?+
cy.intercept('GET', '**/viacep/**', (req) => { req.reply((res) => { res.delay = 15000; res.statusCode = 504; res.body = {}; }); }). Isso simula timeout e erro sem atingir limite real. Essencial para testar fallback e tratamento de erro da aplicação.
Preciso gerar endereço falso (CEP), CPF e CNPJ válidos no mesmo fluxo de cadastro. Como combinar?+
No beforeEach, chame cy.task para cada tipo via Promise.all: Promise.all([cy.task('gerarEndereco'), cy.task('gerarCPF'), cy.task('gerarCNPJ')]).then(([end, cpf, cnpj]) => { ... }). Salve em this.dados e reutilize nos intercepts de todas as APIs do fluxo.
O input CEP tem máscara (00000-000) mas a requisição HTTP envia sem máscara. Como mockar?+
O cy.intercept intercepta APÓS o JavaScript remover a máscara. Digitar '01310-100' no input, o código remove o hífen e faz a requisição (01310100) — mocke essa requisição sem máscara. Correlação permanece idêntica à mask original.