Aprenda a como utilizar a biblioteca NSubstitute em seus testes unitários nesse artigo!
Escrever testes unitários é uma prática comum em projetos onde se existe uma preocupação maior com a qualidade. Eu escrevi uma série sobre testes unitários aqui.
No terceiro artigo da série, foi apresentada a biblioteca Moq, bem como um exemplo de seu uso na escrita de um teste unitário. Ela foi utilizada para realizar a substituição de implementação em interfaces de dependências externas, ou simplesmente para criação de mocks.
Porém, existem uma outra biblioteca amplamente utilizada no mercado, chamada NSubstitute, e que será abordada neste artigo. Também utilizarei o framework de testes xUnit.
Introdução
Pelo tema de inversão de dependencia e mocks terem sido abordados em detalhes nesse artigo, não me estenderei muito nesses conceitos. Mas para lembrar:
- Princípio de Inversão de Dependência: princípio do SOLID que diz respeito a que um módulo de alto nível não deve depender de um módulo de baixo nível. Na prática, classes não devem depender de implementações, e sim de interfaces. Quando a implementação for alterada, considerando que as classes dependam de interfaces dessas classes concretas, alterações não seriam necessárias.
- Mocks: são objetos que simulam o comportamento de objetos reais. Podem definir retornos específicos em seus métodos, de maneira que a classe a consumir eles nem note que algo foi alterado.
Assim como o Moq, o NSubstitute permite criar objetos baseados em interfaces, e definir contratos de retorno determinísticos. Por exemplo, consigo definir que um método de uma interface de Repositório retorne uma lista fixa, ou que retorne uma exceção quando invocado.
Abaixo eu listo e descrevo brevemente os métodos principais do NSubstitute.
- Substitute.For<T>: permite a criação de um objeto substituto de tipo T, onde T ou deve ser uma interface, ou com classes e seus membros que permitam override.
- Método(a, b).Returns(c): define o comportamento de método Método, com os parâmetros a e b, que retornaria o valor c.
- Received().Método(a, b): verifica se o objeto substituto recebeu uma chamada do método Método com os parâmetros passados a e b.
- DidNotReceive().Método(a, b): verifica se o objeto substituto não recebeu uma chamada do método Método com os parâmetros passados a e b.
Passo-a-passo da implementação
Passo 1 – Criando os projetos
Primeiramente, crie um projeto de Biblioteca de Classes (.NET Core). Nesse exemplo, ele é chamado de BlogApp.
Em seguida, crie um projeto de Testes Unitários com xUnit (.NET Core) no Visual Studio 2019, ou via .NET CLI. Nesse exemplo, ele é chamado de BlogApp.UnitTests.
No projeto de testes instale o pacote NSubstitute. Isso pode ser feito via Gerenciador de Pacotes do Nuget.
Ou via .NET CLI.
dotnet add package NSubstitute
Passo 2 – Implementando a funcionalidade
No projeto BlogApp, agora serão definidas duas interfaces correspondentes a um serviço e um repositório, chamados respectivamente de IPostService e IPostRepository. Também é criada a classe que implementa o IPostService. Apenas um método é implementado, o Create, que recebe dois campos de texto: title e content.
Para melhorar a visibilidade disso, vou separá-las em duas pastas, chamadas Services e Repositories.
Logo abaixo estão o serviço e sua interface.
O método Create realiza uma chamada para o método Add do repositório, que por sua vez tem em sua assinatura o tipo de retorno Post, que é um objeto do domínio, e então retorna esse objeto Post obtido (poderia ser uma ViewModel, mas vamos simplificar aqui).
Geralmente já se enviaria o objeto do domínio via parâmetro para o método do repositório, mas nesse exemplo eu quero verificar os parâmetros enviados ao método da dependênca (no caso, o de repositório) utilizando o NSubstitute.
E a interface do repositório (cuja implementação vai ser substituída com NSubstitute), bem semelhante ao do Service por ser um exemplo simples.
Passo 3 – Escrevendo o teste unitário
Com o código a ser testado devidamente implementado, é criada uma classe de teste, no projeto BlogApp.UnitTests, chamada PostServiceTests. Seguindo o padrão AAA (Arrange, Act, Assert), e o padrão de nomenclatura Given_When_Then, crio o método de teste abaixo.
Note o uso dos métodos que listei na Introdução sendo utilizados.
Passo 4 – Executando os testes
Executa-se o teste via Visual Studio 2019, ou .NET CLI.
Sucesso!
Livros sobre Testes Unitários
Assim como comentei neste artigo, onde indiquei 3 livros essenciais para desenvolvedores .NET, os livros seguem sendo uma ótima fonte de informação. Sendo assim, decidi deixar indicação de livros sobre o tema.
Test Driven Development: By Example, Kent Beck
Livro escrito pela lenda Kent Beck, criador do Extreme Programming e Test-Driven Development, e um dos signatários originais do Manifesto Ágil. Livro fantástico sobre o tema, para quem quiser se aprofundar no assunto.
O livro pode ser encontrado aqui, em formato físico.
Test-Driven Development: Teste e Design no Mundo Real com .NET, Casa do Código
O livro pode ser encontrado aqui, em formato físico ou digital.
The Art of Unit Testing: With Examples in C#, Roy Osherove
Com prólogos de autores reconhecidos mundialmente como Michael Feathers e Robert C. Martin, este livro também é uma leitura altamente indicada para aqueles que querem se aprofundar em testes unitários.
O livro pode ser encontrado aqui, em formato físico.
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
Conclusão
O artigo apresentou, tanto de maneira teórica quanto prática, o pacote NSubstitute junto com suas características e um exemplo de aplicação. Caso queira saber mais sobre o NSubstitute, indico olhar a sua documentação.
O NSubstitute se posiciona como uma ótima alternativa ao Moq em projetos tanto de pequeno, quanto de grande porte, que utilizem a prática de escrita de testes unitários.