Para criar testes automatizados em uma integração com API de CPF, use mocks para testes unitários (simulando as respostas sem consumir cota), testes de integração com o plano gratuito da CPFHub.io (50 consultas/mês, sem cartão) e testes end-to-end para validar o fluxo completo. A latência real da API é de ~900ms, então configure timeouts de pelo menos 10 segundos. A API nunca bloqueia por excesso de uso — consultas acima do plano são cobradas a R$0,15/unidade.
Integrar uma API externa ao seu sistema é apenas metade do trabalho. A outra metade é garantir que essa integração funcione corretamente em todos os cenários — sucesso, erro, timeout, dados inesperados. Sem testes automatizados, qualquer alteração no código pode quebrar a integração sem que ninguém perceba até que um usuário real seja afetado.
O OWASP Testing Guide recomenda validar integrações externas em múltiplas camadas, incluindo testes de contrato e testes de resiliência a falhas.
Estratégia de testes para APIs externas
Antes de escrever código, é preciso definir a estratégia. Para integrações com APIs externas, a abordagem mais eficiente é a pirâmide de testes.
Níveis de teste
-
Testes unitários com mocks — Simulam as respostas da API para testar a lógica do seu código sem fazer chamadas reais. São rápidos e devem ser a maioria dos testes.
-
Testes de integração — Verificam se o seu código se comunica corretamente com a API real, usando o plano gratuito da CPFHub.io (50 consultas/mês) como ambiente de teste.
-
Testes end-to-end — Validam o fluxo completo, desde a interface do usuário até a resposta da API.
Testes unitários com mocks em Python
O primeiro passo é isolar a lógica de negócio da chamada à API. Isso permite testar cada cenário sem consumir consultas reais.
Módulo de consulta
import requests
def consultar_cpf(cpf: str, api_key: str) -> dict:
url = f'https://api.cpfhub.io/cpf/{cpf}'
headers = {
'x-api-key': api_key,
'Accept': 'application/json'
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
return response.json()
def validar_dados(cpf: str, nome_esperado: str, api_key: str) -> dict:
resultado = consultar_cpf(cpf, api_key)
if not resultado.get('success'):
return {'valido': False, 'motivo': 'CPF nao encontrado'}
nome_real = resultado['data']['nameUpper']
nome_confere = nome_esperado.upper().strip() in nome_real
return {
'valido': nome_confere,
'nome_real': resultado['data']['name'],
'motivo': 'Dados conferem' if nome_confere else 'Nome divergente'
}
Testes com unittest e mock
import unittest
from unittest.mock import patch, MagicMock
from consulta_cpf import consultar_cpf, validar_dados
class TestConsultaCPF(unittest.TestCase):
@patch('consulta_cpf.requests.get')
def test_consulta_sucesso(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
'success': True,
'data': {
'cpf': '12345678900',
'name': 'Joao da Silva',
'nameUpper': 'JOAO DA SILVA',
'gender': 'M',
'birthDate': '15/06/1990',
'day': 15,
'month': 6,
'year': 1990
}
}
mock_get.return_value = mock_response
resultado = consultar_cpf('12345678900', 'chave_teste')
self.assertTrue(resultado['success'])
self.assertEqual(resultado['data']['name'], 'Joao da Silva')
mock_get.assert_called_once()
@patch('consulta_cpf.requests.get')
def test_consulta_cpf_invalido(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {'success': False}
mock_get.return_value = mock_response
resultado = validar_dados('00000000000', 'Teste', 'chave_teste')
self.assertFalse(resultado['valido'])
self.assertEqual(resultado['motivo'], 'CPF nao encontrado')
@patch('consulta_cpf.requests.get')
def test_timeout(self, mock_get):
mock_get.side_effect = requests.exceptions.Timeout()
with self.assertRaises(requests.exceptions.Timeout):
consultar_cpf('12345678900', 'chave_teste')
@patch('consulta_cpf.requests.get')
def test_nome_divergente(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
'success': True,
'data': {
'cpf': '12345678900',
'name': 'Joao da Silva',
'nameUpper': 'JOAO DA SILVA',
'gender': 'M',
'birthDate': '15/06/1990',
'day': 15,
'month': 6,
'year': 1990
}
}
mock_get.return_value = mock_response
resultado = validar_dados('12345678900', 'Maria Santos', 'chave_teste')
self.assertFalse(resultado['valido'])
self.assertEqual(resultado['motivo'], 'Nome divergente')
if __name__ == '__main__':
unittest.main()
Testes com Jest em JavaScript
Para projetos Node.js, o Jest oferece uma forma simples de criar mocks e testar integrações.
const consultarCpf = async (cpf, apiKey) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
try {
const response = await fetch(
`https://api.cpfhub.io/cpf/${cpf}`,
{
headers: {
'x-api-key': apiKey,
'Accept': 'application/json'
},
signal: controller.signal
}
);
clearTimeout(timeoutId);
return await response.json();
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
};
// Testes
describe('Consulta de CPF', () => {
beforeEach(() => {
global.fetch = jest.fn();
});
test('deve retornar dados quando CPF e valido', async () => {
global.fetch.mockResolvedValue({
json: async () => ({
success: true,
data: {
cpf: '12345678900',
name: 'Joao da Silva',
nameUpper: 'JOAO DA SILVA',
gender: 'M',
birthDate: '15/06/1990',
day: 15,
month: 6,
year: 1990
}
})
});
const resultado = await consultarCpf('12345678900', 'chave_teste');
expect(resultado.success).toBe(true);
expect(resultado.data.name).toBe('Joao da Silva');
expect(global.fetch).toHaveBeenCalledTimes(1);
});
test('deve lidar com CPF nao encontrado', async () => {
global.fetch.mockResolvedValue({
json: async () => ({ success: false })
});
const resultado = await consultarCpf('00000000000', 'chave_teste');
expect(resultado.success).toBe(false);
});
test('deve lidar com erro de rede', async () => {
global.fetch.mockRejectedValue(new Error('Network error'));
await expect(
consultarCpf('12345678900', 'chave_teste')
).rejects.toThrow('Network error');
});
});
Cenários que devem ser testados
| Cenário | O que testar | Tipo de teste |
|---|---|---|
| CPF válido com dados corretos | Retorno completo com success: true | Unitário |
| CPF inexistente | Retorno com success: false | Unitário |
| Timeout da API | Exceção de timeout | Unitário |
| Erro 401 (chave inválida) | Tratamento de erro de autenticação | Unitário |
| Excedente de cota (cobrado) | Lógica de controle de custo | Unitário |
| Erro 500 (erro interno) | Fallback ou mensagem ao usuário | Unitário |
| Nome divergente | Lógica de comparação de nomes | Unitário |
| Chamada real à API | Resposta consistente | Integração |
| Fluxo completo do usuário | Cadastro com validação de CPF | End-to-end |
Testes de integração com a API real
Para testes de integração, use o plano gratuito da CPFHub.io, que oferece 50 consultas por mês sem custo. Marque esses testes para que não sejam executados em todo build.
import os
import unittest
import requests
@unittest.skipUnless(
os.getenv('RUN_INTEGRATION_TESTS'),
'Testes de integracao desabilitados'
)
class TestIntegracaoAPI(unittest.TestCase):
def setUp(self):
self.api_key = os.getenv('CPFHUB_API_KEY')
self.base_url = 'https://api.cpfhub.io/cpf'
def test_resposta_tem_campos_esperados(self):
cpf = '12345678900'
response = requests.get(
f'{self.base_url}/{cpf}',
headers={
'x-api-key': self.api_key,
'Accept': 'application/json'
},
timeout=15
)
self.assertEqual(response.status_code, 200)
dados = response.json()
self.assertIn('success', dados)
if dados['success']:
self.assertIn('data', dados)
self.assertIn('cpf', dados['data'])
self.assertIn('name', dados['data'])
self.assertIn('birthDate', dados['data'])
self.assertIn('gender', dados['data'])
def test_chave_invalida_retorna_401(self):
response = requests.get(
f'{self.base_url}/12345678900',
headers={
'x-api-key': 'chave_invalida',
'Accept': 'application/json'
},
timeout=15
)
self.assertEqual(response.status_code, 401)
Boas práticas
-
Separe testes por tipo — Use marcadores (pytest markers, Jest describe blocks) para distinguir testes unitários, de integração e end-to-end.
-
Nunca exponha chaves de API — Armazene a chave como variável de ambiente e nunca a inclua no código-fonte.
-
Simule cenários de falha — Teste timeouts, erros de rede e respostas inesperadas. Esses cenários são os que mais causam problemas em produção.
-
Automatize no CI/CD — Execute testes unitários em todo commit. Testes de integração podem rodar em intervalos maiores.
-
Mantenha mocks atualizados — Quando o formato da resposta da API mudar, atualize os mocks para refletir a estrutura real.
Perguntas frequentes
Qual é a latência real da API de CPF e como isso afeta meus testes?
A latência da CPFHub.io é de aproximadamente 900ms em condições normais. Nos testes de integração, configure um timeout mínimo de 10 segundos para absorver variações de rede. Nos testes unitários com mock, o timeout não é relevante porque a resposta é simulada localmente.
A API bloqueia as requisições se eu exceder o limite do plano?
Não. A CPFHub.io nunca bloqueia requisições por excesso de uso. Quando o limite mensal do plano é ultrapassado, cada consulta adicional é cobrada a R$0,15. Isso permite continuar os testes de integração sem interrupções, mas fique atento ao custo em suítes de teste que chamam a API real com frequência.
Devo usar TDD ao desenvolver uma integração com API de CPF?
TDD funciona bem nesse contexto: escreva primeiro o teste com mock que define o comportamento esperado (CPF válido retorna nome, CPF inválido retorna erro), depois implemente o código que faz esse teste passar. A separação entre lógica de negócio e chamada HTTP facilita muito a abordagem TDD.
Como estruturar os mocks para cobrir mudanças futuras no contrato da API?
Crie um arquivo centralizado de fixtures com os formatos de resposta esperados (sucesso, erro 401, CPF não encontrado). Assim, se a estrutura do JSON mudar, você atualiza em um único lugar. Considere também testes de contrato com ferramentas como Pact para detectar quebras de contrato antes de ir a produção.
Conclusão
Testes automatizados são a melhor forma de garantir que sua integração com a API de CPF funcione corretamente em todos os cenários. A pirâmide de testes — mocks para unitários, plano gratuito para integração e fluxo real para end-to-end — cobre os riscos sem gerar custo desnecessário. Como a CPFHub.io nunca bloqueia por excesso de uso, o risco de interromper testes em CI/CD por rate limit simplesmente não existe: o controle é financeiro, não operacional.
Comece pelo plano gratuito da CPFHub.io — 50 consultas/mês sem cartão — para montar seu ambiente de testes de integração. Quando o volume crescer, o plano Pro por R$149/mês oferece 1.000 consultas mensais. Cadastre-se em cpfhub.io e coloque sua suíte de testes no ar hoje.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



