Qual a diferença entre um MOCK e um STUB?
Tags: dotnet, tests, unittests, xunit
Published: 2021-10-14 01:02:46

---
title: Qual a diferença entre um MOCK e um STUB?
published: true
description: Nós programadores temos o hábito de "mocar" todo e qualquer recurso para que possamos seguir com o nosso trabalho com menos dependências externas ou impedimentos. Você sabia que existem outros "dublês" de código?
tags: #dotnet #tests #unittests #xunit
series: Testes de Unidade no .NET
---

Recentemente me mandaram a seguinte pergunta: "Qual a diferença entre stub e mock?"

Quando falamos sobre as estratégias utilizadas para testar um código possuímos os seguintes conceitos.

## Fake

O Fake representa uma implementação real mas não necessariamente igual a que será utilizada em ambiente produtivo, como por exemplo um repositório persistido em memória; 

*Obs.: O Fake é uma técnica utilizada em casos de testes integrados, onde nós testamos mais de uma camada em um único cenário de testes.*

**Vejam o exemplo abaixo:**

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=ProdutoRepositoryFake.cs %}

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=FakeSample.cs %}

Estamos criando uma classe concreta chamada ProdutoRepositoryFake que efetivamente implementa a interface IProdutoRepository, porém de uma forma simplificada, e potencialmente diferente da que será publicada em produção.

## Spy 

Spies são utilizados em casos onde queremos validar o comportamento de um método e sua interação com suas dependências, neste caso as dependências não são modificadas;

*Obs.: O Spy é uma técnica utilizada em casos de testes Integrados, onde nós testamos mais de uma camada em um único cenário de testes.*

**Vejam o exemplo abaixo:**

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=SpySample.cs %}

Estamos aplicando um Spy no nosso ProdutoRepositoryFake (pois nesse código de exemplo é a unica classe concreta que deriva de IProdutoRepository que nós temos), este mesmo exemplo poderia ser aplicado com qualquer classe concreta.

Neste exemplo foi preciso usar a interface IProdutoRepository e a classe ProdutoRepositoryFake como base para isso (linha 4).

Por que o código da linha 3 não funciona? Não funciona porque os métodos em questão não possuem o modificador "virtual", ou seja, ele não pode ser sobrescrito.

## Stub

Stub é uma implementação que nos permite fornecer respostas prontas, são utilizados para cenários onde queremos validar apenas o resultado;

**Vejam o exemplo abaixo:**

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=StubSample.cs %}

Estamos criando um stub de um IProdutoRepository onde sempre que o método Obter for chamado passando o parâmetro id igual a 1, ele deve retornar um Produto { Id = 1, Nome = "TECLADO" }

*Obs.: Está sendo utilizado um framework para simplificar a implementação do Stub, em um cenário natural, seria necessário criar um ProdutoRepositoryStub que imlpementasse a interface IProdutoRepository, o que seria muito mais verboso.*

## Mock

Diferentemente do Stub, o mock possui a capacidade de validar o comportamento da implementação, validando por exemplo quantas vezes um determinado método foi chamado, quais foram os parâmetros passados dentre outras informações, ou seja, o mock possui a capacidade do Spy e do Stub juntas.

**Vejam o exemplo abaixo:**

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=MockSample.cs %}

Estamos criando uma instancia do IProdutoRepository utilizando um Mock, sendo assim nós conseguimos definir arbitrariamente o retorno para os métodos que esta interface possui.

Além disso nós conseguimos também validar posteriormente se um determinado método foi chamado, com quais parametros foi chamado e quantas vezes ele foi chamado.

## Dummy

Um objeto dummy é um objeto que nós utilizamos apenas para viabilizar a execução do nosso código, mas que para o nosso teste ele não será utilizado em momento algum.

**Vejam o exemplo abaixo:**

{% gist https://gist.github.com/fructuoso/0bef959de3abe39a3ba5cd1df8820bc5 file=DummySample.cs %}

Estamos criando um método auxiliar que produz um Produto válido. Para o escopo do nosso teste é irrelevante conhecer as características de um produto válido, os valores atribuídos nas propriedades deste objeto também são irrelevantes.

Imagine um cenário onde temos dezenas de testes que precisam receber um Produto válido, eis que uma nova regra de validação é criada.

Automaticamente TODOS os testes que dependem de um Produto válido começarão a falhar (o que é bom), se não fosse pelo Dummy seria necessário modificar todos os testes um a um.

### Considerações Finais

Segue o repositório no GitHub com os exemplos utilizados [link](https://github.com/fructuoso/Doubles.Types)

É válido lembrar que para estes exemplos estou usando o Moq que reduz significantemente a complexidade de escrever um duble de código.

Agora, mesmo que você prefira continuar falando que vai mocar tudo, você entende e sabe a diferença de cada uma dessas técnicas.

Se você gostou aproveite para deixar o seu Like e me seguir aqui e nas outras redes [link](https://linktr.ee/fructuosodev)

###Referências
[Mocks Aren't Stubs](https://martinfowler.com/articles/mocksArentStubs.html)