Gerando mocks de interfaces no go!
Tags: go, testing, mock, tutorial
Published: 2021-11-10 16:15:07

## Introdução
Com a geração de mocks é possível aumentar a nossa produtividade na hora de escrever teste e também possuir uma melhor organização e padronização.

Para a exemplificação, irei utilizar um repositório com alguns conceitos de [clean architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html), onde possuímos as interfaces do domain que serão implementados na camada de infra.

A ideia básica é que no domain possuímos nossas entidades que contêm a regra de negócio (estruturas e métodos), na camada de infra é onde iremos implementar os métodos do domain, e por fim os use cases que irão fazer a nossa regra girar para conversar com o resto da aplicação.

Seguimos com a estrutura do projeto:

![Estrutura do projeto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avuy8xgvxa8n6180qc5m.png)

## Gerando os mocks

A interface que será gerada possui os seguintes métodos:
![Imagem da interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/blpea1pwuo3ixmefdju6.png)

O primeiro passo para gerarmos o mock é rodar o comando abaixo, para instalar o cli do [mockgen](https://github.com/golang/mock):
### < 1.16
```
$ GO111MODULE=on go get github.com/golang/mock/mockgen@v1.6.0
```
### > 1.16
```
$ go install github.com/golang/mock/mockgen@v1.6.0
```
 
Após instalado iremos rodar o comando para gerar os nossos mocks:
```
$ mockgen -source=./domain/car_storage.go -destination ./infra/mock/mock.go
```
Na tag ***source*** iremos informar o caminho da nossa interface e na ***destination*** (podemos destinar para qualquer pasta) onde irá ser gerado o arquivo contendo os mocks.

O arquivo gerado é composto pelos seguintes métodos:
- NewMock que criar uma instância;
- EXPECT que retorna os métodos do nosso Mock;
- Os métodos da interface em si que retornam os valores que desejamos.

## Utilizando os mocks gerados

Após criar um arquivo _test e declarar nossa função, primeiro devemos instanciar nosso controller, este controller vem do package [mock](github.com/golang/mock) e dentro deles passamos o nosso t (instância do tipo *testing.T), após isso devemos criar a nossa variável do mock passando este nosso controller que foi gerado.

![usando o mock](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nk2ophoaogrqj7qfu2tl.png)
 
Para utilizarmos agora a nossa variável, iremos chamar o método EXPECT() e ele irá retornar os métodos da nossa interface. Após chamarmos o nosso método e passar o que ele espera, iremos decidir o que ele irá retornar em um dos 2 métodos abaixo.

- Return: recebe diretamente o que irá retornar;
- DoAndReturn: recebe uma função que irá fazer algo e depois retornar.

Aqui estão alguns exemplos que utilizei para mostrar cada método:

![Teste completo com o DoAndReturn](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/et71caxxyacsz6gg5xaq.png)
 

![Teste completo com o Return](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ez6ifdfo2uktdrgqify.png)

Vemos que o meu serviço recebe a minha instância mockada e após declararmos o que o nosso mock irá retornar, chamo o método Save do serviço que dentro do mesmo, irá chamar o método SaveCar da nossa instância mockada.

## Métodos extras

- Times:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miqt0d8sy2q7p9vobjh6.png)

- AnyTimes: após chamar este método, podemos utilizar quantas vezes quiser o nosso método
- MaxTimes: máximo de vezes que o método pode ser chamado
- MinTimes: minimo de vezes que o método pode ser chamado

## Considerações finais:
 Espero que tenham gostado, minhas redes estão no meu perfil do dev.to para quaisquer dúvidas ou informações!
 

## Código fonte
- [GITHUB](https://github.com/hyperyuri/go-mocking)