RESPX intercepta requisições do HTTPX e devolve respostas controladas. Assim, um teste valida sucesso, erro e timeout sem depender de rede, credenciais ou disponibilidade externa.

Simular uma rota

python -m pip install pytest httpx respx
import httpx


def obter_status(client: httpx.Client) -> str:
    response = client.get("https://api.example.com/status")
    response.raise_for_status()
    return response.json()["status"]


def test_obter_status(respx_mock) -> None:
    rota = respx_mock.get("https://api.example.com/status").respond(
        200, json={"status": "ok"}
    )
    with httpx.Client() as client:
        assert obter_status(client) == "ok"
    assert rota.called

Registre apenas as rotas esperadas. Uma URL ou método inesperado deve falhar, pois pode indicar regressão no contrato. Valide também corpo, query e headers relevantes, sem acoplar o teste a detalhes sem importância.

O guia de HTTPX em Python cobre clientes e timeouts. Para corrotinas, combine RESPX com pytest-asyncio.

Falhas e limites

Definir o escopo do router

A fixture respx_mock remove rotas após cada caso. @respx.mock oferece isolamento como decorator; with respx.mock: restringe a interceptação a um bloco. Mantenha a ativação estreita. Rotas devem explicar cada requisição externa. Uma chamada sem correspondência costuma indicar mudança de método, host, caminho ou query. Evite respostas catch-all que escondem regressões.

Verificar o contrato relevante

Rotas podem restringir método, URL, query, headers e conteúdo. Verifique apenas detalhes prometidos pelo cliente. Paginação pertence ao contrato; ordem incidental de chaves JSON não.

def test_envia_pagina_e_token(respx_mock) -> None:
    rota = respx_mock.get(
        "https://api.example.com/items",
        params={"page": "2"},
        headers={"authorization": "Bearer token-de-teste"},
    ).respond(200, json={"items": []})

    with httpx.Client() as client:
        resposta = client.get(
            "https://api.example.com/items",
            params={"page": 2},
            headers={"authorization": "Bearer token-de-teste"},
        )

    assert resposta.json() == {"items": []}
    assert rota.call_count == 1

Nunca use token de produção numa fixture. Um valor claramente fictício prova a composição do header sem introduzir segredo.

Inspecionar a requisição capturada

O histórico expõe o httpx.Request, útil quando colocar todo o payload no matcher prejudicaria a falha.

request = rota.calls.last.request
assert request.method == "GET"
assert request.url.params["page"] == "2"

Em JSON, compare a estrutura decodificada, não espaços ou ordem. Verifique credenciais apenas por presença ou valor sintético e não imprima autorização numa assertion personalizada. Com várias chamadas, confira contagem e sequência relevante.

Cobrir AsyncClient

RESPX intercepta httpx.AsyncClient no mesmo router. Combine-o com pytest-asyncio e aguarde o código normalmente.

@pytest.mark.asyncio
async def test_status_async(respx_mock) -> None:
    rota = respx_mock.get("https://api.example.com/status").respond(
        200, json={"status": "ok"}
    )
    async with httpx.AsyncClient() as client:
        assert await buscar_status(client) == "ok"
    assert rota.called

Injete clientes na aplicação. Construção oculta dificulta controlar timeout, transporte, base URL e ciclo de vida. Uma fixture compartilhada precisa fechar o cliente depois de yield.

Distinguir HTTP e transporte

Um 503 é resposta HTTP válida e chega a raise_for_status(). ConnectTimeout, ReadTimeout e ConnectError ocorrem antes de uma resposta utilizável. Use side_effect:

respx_mock.get("https://api.example.com/status").mock(
    side_effect=httpx.ConnectTimeout("connection timed out")
)

Verifique o erro estável da aplicação, não toda a mensagem da dependência. Confirme que 4xx não elegível não recebe retry e que falhas elegíveis respeitam o limite. Injete sleep ou backoff para o teste não esperar segundos reais.

Testar sequências de retry

Um teste deve mostrar falha intermediária e resultado final. A rota pode devolver respostas sucessivas ou usar callback contador. Verifique valor final e número exato de tentativas. Inclua o esgotamento para revelar erros de contagem.

A política pertence à produção; RESPX só oferece observações. A aplicação decide erros, espera e segurança da repetição. Repetir POST pode duplicar ação sem chave de idempotência.

Usar callbacks com moderação

Um callback lê a requisição e devolve httpx.Response, útil para paginação ou resposta dependente da entrada. Mantenha-o muito mais simples que o serviço. Recriar validação, autenticação e armazenamento produz uma segunda implementação sujeita ao mesmo equívoco.

Prefira respostas estáticas. Pequenas fábricas ajudam quando testes compartilham payload documentado e alteram campos relevantes. Grandes respostas de produção escondem o comportamento testado.

Separar camadas de teste

RESPX verifica a reação ao contrato da fixture; não prova que o provedor ainda o implementa. Mantenha poucos testes de contrato ou sandbox em ambiente controlado. Separe-os da suíte offline e proteja credenciais.

Registre fonte e data de fixtures representativas. Atualize-as após consultar documentação oficial ou captura sanitizada, não apenas para deixar o teste verde. End-to-end deve ser reduzido porque depende de disponibilidade externa.

Bloquear rede acidental

Revisar a qualidade das fixtures

Resposta simulada é dado de teste e merece revisão. Use o menor payload que preserve o comportamento, mas mantenha campos obrigatórios e tipos realistas. Nomeie fábricas pelo conceito do provedor, não pelo nome de um teste. Uma descrição OpenAPI pode orientar o formato, porém o cenário ainda exige revisão humana.

Quando um incidente revelar resposta não prevista, adicione primeiro uma fixture sanitizada e uma assertion que reproduza a falha, depois corrija o adapter. Não copie dados pessoais, tokens, identificadores de trace nem corpos proprietários para o repositório. Registre por que aquele formato é representativo.

Organizar manutenção e diagnóstico

Deixe base URL e construção do cliente num único adapter, facilitando atualizar versão, autenticação e timeouts. Fixtures podem ficar próximas dos testes quando são específicas; fábricas compartilhadas pertencem a um módulo pequeno, sem transformar todos os casos numa abstração difícil de ler.

Uma falha deve mostrar rota esperada, chamada recebida e diferença relevante, sem segredos. Confirme que assertions do router executam mesmo quando outra assertion falha. Uma rota esperada e não usada pode indicar curto-circuito correto, então torne essa expectativa explícita.

Antes do merge, rode o teste sem acesso à rede, confira sucesso, status inválido e erro de transporte, e execute a suíte completa. Revise também compatibilidade entre versões fixadas de HTTPX e RESPX. Se a atualização mudar transporte ou matching, adapte um caso de cada padrão antes de aplicar mudança mecânica em todas as fixtures.

Também cubra paginação quando o cliente a implementa. A primeira resposta deve fornecer o cursor e a segunda validar que ele foi enviado corretamente. Limite o número de páginas para testar proteção contra cursor repetido. Em downloads, valide streaming, fechamento e tratamento de resposta truncada sem manter arquivos grandes no repositório.

Para uploads, compare nome, media type e bytes essenciais, evitando depender do boundary aleatório do multipart. Se a aplicação assina requisições, injete relógio e credencial fictícia para produzir assinatura determinística. Esses testes pertencem ao adapter, pois expressam o protocolo externo.

Ative router estrito e registre endpoints esperados. Centralize clientes com base URL, timeouts e injeção. Um hostname inesperado fica visível imediatamente.

Cubra redirects, JSON inválido, corpo vazio, rate limit, autenticação e resposta parcial conforme o contrato do adapter. Não teste cada recurso do HTTPX; foque decisões próprias. Verifique chamadas quando a presença ou ausência da requisição for um resultado.

Use side_effect para simular httpx.ConnectTimeout ou uma sequência de respostas. Isso permite verificar retry e mensagens de erro de forma determinística. Não replique toda a API remota no mock: mantenha exemplos mínimos e acrescente testes de contrato separados para detectar mudanças reais.

A documentação oficial do RESPX, consultada em 22 de julho de 2026, apresenta fixture, padrões de rota, respostas e histórico de chamadas. Fixe versões compatíveis de RESPX e HTTPX para evitar mudanças inesperadas na integração.