Testes Unitários com C# e xUnit – Parte 4: Criando dados Mock com AutoFixture

Olá! Depois de um tempo sem publicar sobre Testes Unitários, vou agregar mais um artigo para essa série falando sobre o AutoFixture!

Vou escrever sobre suas principais características, benefícios, e como utilizá-lo na prática na escrita de Testes Unitários.

Caso tenha interesse em ler mais sobre Testes Unitários, deixo abaixo os outros artigos da série.

Repositório da série de artigos no Git aqui.


Quer ser notificado sobre os próximos artigos, lives semanais, eventos e treinamentos? Entre no canal LuisDev no Telegram!


Test Fixture

Primeiramente, é importante entender o conceito de Test Fixture. De maneira simples, Test Fixture é o ambiente fixo e bem definido onde os testes são executados, e seus resultados repetíveis. Quando definimos um mock no artigo anterior estávamos alterando o Test Fixture.

Dito isso, em diversas situações precisamos definir mocks para chamadas de métodos de dependências. Pode ser o método de uma interface de Repository, ou de um serviço de Integração, por exemplo. A grande questão é que em diversas situações os valores utilizados não tem um impacto no resultado do teste unitário.

Por exemplo, em um método de um serviço de camada Application, responsável por consultar o banco de dados através de um Repository e formatar os dados para retorno, não faz muita diferença se a lista resultante tem 1, 2, ou 3 elementos. O que importa é que o método mapeie corretamente. Se forem 2 objetos retornados do Repository, ele tem que retornar 2 objetos de modelo de saída (View Models).

O que quis dizer com tudo isso? É que se torna uma tarefa repetitiva. Acabamos utilizando Factories estáticos para retornar esses dados fixos (ou “chumbados”), sendo que em várias situações não seria necessário algo tão elaborado. E o AutoFixture ajuda exatamente nisso.


O que é o AutoFixture

É uma biblioteca open-source que acelera bastante a fase de Arrange do Padrão Arrange-Act-Assert (AAA) para testes unitários. Se não está familiarizado (a) com esse padrão, esse artigo vai te ajudar.

Ao invés de ficar criando objetos para parâmetros de seus métodos sob testes, ou de retornos de consultas, é possível criar objetos de maneira bem simples e prática.

Instalando

Como qualquer pacote Nuget, podemos instalá-lo via Gerenciador de Pacotes do Nuget, como na figura abaixo.

Instalando a biblioteca AutoFixture pelo Gerenciador de Pacotes Nuget

Ou via linha de comando .NET CLI.

Instalando via Linha de Comando .NET CLI

Principais métodos

Primeiramente, tudo vai começar com a criação da instância da classe Fixture, com seu construtor sem parâmetros.

Instanciando a classe Fixture

Vou listar abaixo os 2 métodos que você vai mais utilizar. Tem mais na documentação, que deixo na sessão de Referências deste artigo.

  • Create<T>(): permite a criação de um objeto da classe T, com valores definidos pela classe Fixture. Provavelmente é o método que mais utilizará durante a escrita de testes unitários. Exemplos de uso são objetos de entrada na camada de aplicação, ou Commands/Queries que serão processados pelos seus respectivos Handlers.
  • CreateMany<T>(): permite a criação de uma lista de objetos de tipo T, com valores definidos pela classe Fixture. O tamanho padrão é 3, mas você pode definir manualmente através da propriedade RepeatCount da classe Fixture.

A seguir vou construir cenários de teste para utilizar ambos métodos.


Exemplo prático

Um cenário simples de se utilizar o AutoFixture é no teste unitário ContaExistenteNotificacaoFuncionando_ChamadoDocumentoValido_RetornarSucesso da classe ContaCorrenteServiceNotificarContaCorrenteTests.cs.

Ufa, que nome longo né? Se estiver estranhando ele, saca a parte 2 dessa série, onde explico sobre o padrão Given_When_Then e sobre como o tamanho do nome do método não ser um problema em testes unitários.

Continuando, nesse método utilizamos um Factory estático para obter um objeto ContaCorrente e “mockar” o retorno do método ObterDocumento do IContaCorrenteRepository. Porém, se pensar bem, os dados dela pouco importam! Afinal, a única verificação que é feita é sobre a ContaCorrente ser nula ou não. O restante diz respeito ao INotificacaoService, que já está mockado usando a biblioteca Moq.

Implementação atual do método NotificarContaCorrente

Dito isto, podemos refatorar o teste unitário para a versão abaixo, utilizando a classe Fixture para gerar o objeto de ContaCorrente.

Refatoração do Teste Unitário utilizando AutoFixture

Note uma coisa curiosa: foi utilizado a classe Fixture para gerar o objeto atribuído a contaCorrente, mas não a respostaNotificacaoViewModel. O motivo é que esse último AFETA o resultado final caso a propriedade Sucesso seja falso. Nesse caso, definimos manualmente utilizando o Factory. Ou, caso tenha set público, poderia gerar com o Fixture e mudaria o valor de Sucesso para true antes de mockar o método Notificar.

Já para testar a criação de múltiplos objetos com o método CreateMany, eu criei uma classe simples que representaria uma listagem de operações na conta corrente (poderia também ter data de criação, e outros dados, mas quis simplificar).

Classe simples para representar dados de operações em uma Conta Corrente

Logo abiaxo mostro o código ara gerar de como gerar uma lista de 5 objetos dessa classe.

Gerando uma lista de 5 objetos de tipo OperacaoContaCorrente

Debuguei esse código para mostrar o resultado da lista e os valores preenchidos pela classe Fixture.

Debugging mostrando a geração de objetos com AutoFixture

Concluindo

Foi apresentado a biblioteca AutoFixture, junto com suas características, principais métodos, e aplicação prática do projeto do Github utilizado para a série de artigos.

Espero que possa fazer bom uso dele, e reduzir a quantidade de código escrito em seus Testes Unitários para a criação de objetos que podem facilmente ser gerados pelo AutoFixture. Lembrando que nem todos objetos podem ser gerados assim, já que exigem um estado específico para ser validado pelo teste unitários.

Curtiu o artigo? Compartilha no LinkedIn, nos grupos de TI e/ou com seus amigos.


Quer alavancar sua carreira como Desenvolvedor(a) .NET?

Opa, aqui é o Luis Felipe (LuisDev), criador do blog LuisDev.

Além de Desenvolvedor .NET Sênior, eu sou instrutor de mais de 700 alunos e também tenho dezenas de mentorados.

Conheça o com mais de 800 video-aulas sobre C# e desenvolvimento de APIs com ASP NET Core, Microsserviços com ASP NET Core, Arquitetura de Software, Computação em Nuvem, SQL, HTML, CSS e JavaScript, JavaScript Intermediário, TypeScript, Desenvolvimento Front-End com Angular, e Desenvolvimento Front-end com React. Diversos mini-cursos disponíveis aos alunos e atualizações gratuitas.

Suporte dedicado, e comunidade de centenas de alunos.

Completo e online, destinado a profissionais que querem dar seu próximo passo em sua carreira como desenvolvedores .NET.

Clique aqui para ter mais informações e garantir sua vaga


Referências

Github do AutoFixture: https://github.com/AutoFixture/AutoFixture

Cheatsheet: https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet