Módulo 13 - Testes avançados
Mocks e monkeypatch: isolar dependências
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Entender por que isolar dependências externas nos testes.
- Substituir uma função por um Mock e verificar como foi chamada.
- Usar monkeypatch para trocar atributos e variáveis de ambiente no teste.
- Saber a fronteira: testar o seu código, não a biblioteca de terceiros.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Mocks e monkeypatch: isolar dependências.
Os objetivos desta aula. Entender por que isolar dependências externas nos testes. Substituir uma função por um Mock e verificar como foi chamada. Usar monkeypatch para trocar atributos e variáveis de ambiente no teste. Saber a fronteira: testar o seu código, não a biblioteca de terceiros.
Veja o essencial, parte por parte.
Por que isolar dependências. Um teste não deve mandar e-mail de verdade, cobrar cartão nem depender da internet.
Substituir e verificar com Mock. O módulo unittest.mock, embutido no Python, oferece o objeto Mock e a função patch para trocar dependências.
monkeypatch: trocar o ambiente no teste. O pytest oferece a sua própria ferramenta para isso, a fixture monkeypatch, e ela é especialmente conveniente para trocar atributos, funções de módulo e variáveis de ambiente.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Por que isolar dependências
Boa parte do código útil conversa com o mundo externo: envia e-mails, chama serviços na rede, lê a data e a hora atuais, grava em um banco. Testar esse código do jeito ingênuo seria um problema. Você não quer disparar um e-mail de verdade a cada rodada de testes, nem depender de a internet estar de pé, nem ver o teste falhar amanhã só porque a data mudou. A solução é isolar: no teste, você troca a dependência real por um dublê que você controla e observa.
Esse dublê tem dois papéis. Primeiro, ele evita o efeito colateral real: em vez de mandar o e-mail, apenas anota que o envio foi pedido. Segundo, ele permite verificar o comportamento do seu código: você pode conferir que a função de envio foi chamada uma vez, com o destinatário e o assunto certos. Assim o teste não valida se o servidor de e-mail funciona, o que não é sua responsabilidade, e sim se o seu código o usou corretamente. É essa fronteira que dá foco ao teste.
Sem isolar (frágil)
- Manda e-mail ou cobra de verdade no teste
- Depende da rede e de serviços externos
- Falha por motivos fora do seu código
- Lento e imprevisível
Com mock (isolado)
- Substitui a dependência por um dublê
- Roda offline, sempre igual
- Falha só quando o seu código está errado
- Rápido e determinístico
Substituir e verificar com Mock
O módulo unittest.mock, embutido no Python, oferece o objeto Mock e a função patch para trocar dependências. Um Mock aceita qualquer chamada e a registra, guardando com quais argumentos foi chamado e quantas vezes. Depois, você faz asserções sobre isso: confirmar que foi chamado uma vez, com os argumentos esperados. A ideia é substituir a função real de envio por um Mock, rodar o seu código e então perguntar ao Mock como ele foi usado.
from unittest.mock import Mock
def notificar(usuario, enviar_email):
# enviar_email e injetado; no teste, sera um Mock.
assunto = "Bem-vindo"
enviar_email(usuario["email"], assunto)
return True
def test_notificar_usa_email_certo():
email_falso = Mock()
usuario = {"nome": "Ana", "email": "ana@exemplo.com"}
resultado = notificar(usuario, email_falso)
assert resultado is True
# Verifica COMO o mock foi chamado, sem enviar nada de verdade:
email_falso.assert_called_once_with("ana@exemplo.com", "Bem-vindo")O Mock substitui o envio real; assert_called_once_with verifica os argumentos.
Repare no desenho do código. A função notificar recebe enviar_email como parâmetro, em vez de importar uma função fixa. Esse padrão, chamado injeção de dependência, facilita muito o teste: basta passar um Mock no lugar da função real. Quando a dependência não é injetável assim, e está embutida como uma chamada direta a outro módulo, entra o patch, que substitui temporariamente aquela referência. Em ambos os casos, o objetivo é o mesmo: controlar o que a dependência faz e observar como ela foi usada.
monkeypatch: trocar o ambiente no teste
O pytest oferece a sua própria ferramenta para isso, a fixture monkeypatch, e ela é especialmente conveniente para trocar atributos, funções de módulo e variáveis de ambiente. A grande vantagem é a segurança: tudo que você altera com o monkeypatch é desfeito automaticamente ao fim do teste, sem risco de a mudança vazar para outros testes. É a ferramenta ideal para controlar coisas globais como a hora atual ou uma variável de ambiente de configuração.
import time
def eh_horario_comercial():
hora = time.localtime().tm_hour
return 9 <= hora < 18
def test_horario_comercial(monkeypatch):
class FakeTime:
tm_hour = 10
# Troca time.localtime so durante este teste:
monkeypatch.setattr(time, "localtime", lambda: FakeTime)
assert eh_horario_comercial() is True
def test_fora_do_horario(monkeypatch):
class FakeTime:
tm_hour = 22
monkeypatch.setattr(time, "localtime", lambda: FakeTime)
assert eh_horario_comercial() is Falsemonkeypatch.setattr troca time.localtime só no teste; a hora vira controlável.
Sem o monkeypatch, testar eh_horario_comercial seria uma loteria: o resultado dependeria da hora em que você rodasse os testes. Com ele, você fixa a hora e testa os dois cenários de forma determinística. Vale a mesma advertência das dependências injetadas: você não está testando o módulo time, e sim a lógica que decide com base na hora. A troca serve para controlar a entrada e verificar a sua decisão, mantendo o teste focado no que é seu.
Teste rápido
Por que usar um mock ao testar código que envia e-mail?
Perguntas frequentes
- Qual a diferença entre Mock e monkeypatch?
- Mock, do unittest.mock, é o objeto dublê que substitui uma dependência e registra chamadas. monkeypatch é uma fixture do pytest que troca atributos, funções e variáveis de ambiente durante o teste e desfaz a troca no fim. É comum usar monkeypatch para instalar um Mock no lugar de uma função real.
- O que é injeção de dependência e por que ajuda no teste?
- É passar as dependências de uma função como parâmetros, em vez de fixá-las dentro dela. Isso permite, no teste, passar um dublê no lugar da coisa real, sem precisar de patch. Código escrito assim é naturalmente mais testável, e a técnica combina com todo o resto do módulo.
- Posso exagerar no uso de mocks?
- Sim, e é um erro comum. Mockar demais deixa o teste preso à implementação, quebrando a cada refatoração, e pode dar falsa confiança, já que você testa dublês e não o comportamento real. Use mocks nas fronteiras externas, como rede e e-mail, e prefira objetos reais para a lógica interna sempre que der.
- Por que o monkeypatch é mais seguro que trocar o atributo na mão?
- Porque ele registra a alteração e a desfaz automaticamente ao fim do teste. Se você trocasse um atributo de módulo manualmente e esquecesse de restaurar, a mudança vazaria para outros testes, causando falhas misteriosas. O monkeypatch garante o isolamento sem você precisar lembrar da limpeza.
- Testar com mocks não deixa de testar o código de verdade?
- O mock isola a dependência externa, não o seu código. Você continua exercitando a sua lógica de verdade; apenas substitui o que está fora do seu controle. Para ganhar confiança de que as peças funcionam juntas, complemente os testes com mock por alguns testes de integração que usam as dependências reais.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.