Ao escrever código de teste, há um obstáculo inevitável.
Aquele momento de dúvida: “Isso é Mock ou Stub?”
Às vezes parecem apenas “objetos falsos”, mas ouvir numa revisão de código “Isso não é Mock, é Stub” deixa qualquer um perdido.
Neste artigo, vou organizar de forma clara, com exemplos, as diferenças entre os cinco irmãos dos dublês de teste (Dummy, Stub, Spy, Mock e Fake).
Vamos começar pela conclusão.
Dublês de teste se diferenciam pelo “que está sendo verificado”. Se retorna valores, é Stub; se registra chamadas, Spy; se avalia se as chamadas eram esperadas, Mock; e, se funciona como o real, Fake.
Só de lembrar dessa frase, metade do caminho está concluída.
Afinal, o que é um dublê de teste?
Test Double (dublê de teste) vem do “dublê de cenas perigosas (stunt double)” do cinema.
Assim como o dublê executa cenas perigosas no lugar do ator, o termo designa objetos falsos que substituem os objetos reais.
Gerard Meszaros organizou esse conceito sistematicamente em 『xUnit Test Patterns』 (2007).
Portanto, Mock e Stub são subtipos de dublês de teste.
Por que usá-los? Ao testar a lógica de pagamento, por exemplo, não dá para chamar a API real da operadora de cartão.
É lento, custa dinheiro e, se a rede cair, o teste também falha.
Por isso, colocamos um dublê no lugar do sistema real.
Diferenças entre Mock, Stub, Spy e Fake em uma tabela
Explicações em texto confundem, então vamos começar pela tabela.
| Tipo | Função principal | O que é verificado |
|---|---|---|
| Dummy | Apenas ocupa o lugar | Não verifica |
| Stub | Retorna um valor definido | Estado (resultado) |
| Spy | Registra o histórico de chamadas | Estado + histórico de chamadas |
| Mock | Avalia se a chamada era esperada | Comportamento (chamada) |
| Fake | Funciona de forma leve, como o real | Estado (resultado) |
Aqui, há apenas uma distinção realmente importante.
Verificação de estado ou de comportamento?
Stub e Fake verificam “se o resultado saiu como esperado” (verificação de estado).
Mock verifica “se o método realmente foi chamado” (verificação de comportamento).
Spy fica no meio-termo e registra discretamente as chamadas.
O código torna isso muito mais claro
Código explica mais rápido que palavras. Vamos usar uma função de notificação de usuário como exemplo. Em Swift, é comum criar diretamente dublês de teste que adotam um protocolo.
Primeiro, Stub: um dublê que retorna apenas valores definidos.
// getNameFixar para sempre retornar “Hong Gil-dong”
final class UserRepositoryStub: UserRepository {
func getName(id: Int) -> String { "Hong Gil-dong" }
}
let service = GreetingService(repository: UserRepositoryStub())
// Verificar apenas se o valor do resultado (estado) está correto
#expect(service.greet(id: 1) == "Hong Gil-dong")
O próximo é Mock. Ele verifica “se este método foi chamado”.
// Verificar se a notificação foi realmente enviada (chamada)
final class NotificationSenderMock: NotificationSender {
var sendCallCount = 0
func send(_ message: String) { sendCallCount += 1 }
}
let mockSender = NotificationSenderMock()
let service = UserService(sender: mockSender)
service.notifyUser(id: 1)
// Verificação de comportamento: sendfoi chamado exatamente 1vezes?
#expect(mockSender.sendCallCount == 1)
Percebe a diferença? Stub verifica o valor retornado (resultado), enquanto Mock verifica o número de chamadas.
Essa diferença de perspectiva é essencial para entender os dublês de teste.
Então, quando usar Spy e Fake?
Spy envolve um objeto real: mantém seu comportamento, mas registra as chamadas discretamente.
Use quando “você quer manter a lógica real, mas também saber quantas vezes foi chamado”.
Em Swift, é comum criar uma classe Spy que delega à implementação real e registra em propriedades os argumentos e a quantidade de chamadas.
Fake funciona de modo parecido com o real, mas é uma implementação muito mais leve.
Os exemplos mais comuns são um armazenamento em memória no lugar do banco real ou um repositório falso criado com Dictionary.
Ele funciona como o real, mas é insuficiente para produção: uma implementação feita exclusivamente para testes.
Resumindo, fica assim.
- Só preciso de um valor → Stub
- Preciso verificar se foi chamado → Mock
- Preciso do comportamento real + registro de chamadas → Spy
- Preciso de uma implementação leve que funcione como a real → Fake
Perguntas frequentes
P. Na prática, posso misturar Mock e Stub?
Na prática, uma única classe de dublê de teste feita à mão costuma acumular os papéis de retornar valores (Stub) e registrar chamadas (Mock), então a fronteira fica nebulosa. Ainda assim, é preciso distinguir se o objetivo é fornecer um valor ou verificar uma chamada, para deixar clara a intenção do teste.
P. Ouvi dizer que usar Mock demais faz mal.
O uso excessivo da verificação de comportamento faz os testes quebrarem em cascata com qualquer pequena mudança na implementação interna. Por isso, recomenda-se priorizar a verificação de estado (Stub e Fake) e usar Mock apenas nas relações de colaboração realmente necessárias.
Em vez de decorar os cinco tipos, pergunte a si mesmo: “Agora preciso de um valor ou verificar uma chamada?”
Com essa única pergunta, você naturalmente saberá qual dublê criar.
Se voltar a ficar em dúvida ao escrever testes, abra este artigo novamente. Espero que seus testes fiquem muito mais sólidos!

