Testes e qualidade de código

Guia de dublês de teste: Mock, Stub, Spy e Fake

Ao escrever código de teste, há um obstáculo inevitável.

4 min de leitura
Imagem de capa de Guia de dublês de teste: Mock, Stub, Spy e Fake

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.

Código de teste unitário do Swift Testing verificando classes Mock e Stub com #expect
No fim, olhando o código, fica muito clara a diferença entre verificar o valor retornado e contar chamadas.

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.

  1. Só preciso de um valor → Stub
  2. Preciso verificar se foi chamado → Mock
  3. Preciso do comportamento real + registro de chamadas → Spy
  4. Preciso de uma implementação leve que funcione como a real → Fake
Na dúvida, siga este fluxograma e decida apenas entre valor e chamada.
Na dúvida, siga este fluxograma e decida apenas entre valor e chamada.

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!