ASP .NET Core API - Testes de unidade : Roteiro básico - II
Hoje vamos continuar a realização dos testes de unidade em um projeto ASP .NET Core API que realiza um CRUD. |
Continuando a primeira parte do artigo vamos agora iniciar os nossos testes de unidade.
|
O teste unitário é a metodologia de teste mais popular e ajuda a testar cada pequena unidade do código-fonte sendo usado para simular a dependência do código para que a unidade individual do código seja testada separadamente sem incluir a dependência no código de teste.
Normalmente, em um aplicativo de software, a unidade é uma classe ou um método em uma classe. Se a classe tiver alguma dependência, para testar a unidade do código, simulamos a dependência para obter um acoplamento fraco. O Teste Unitário pode ser feito por um desenvolvedor e o desenvolvedor pode testar a qualidade do código.
Além dos testes de unidade temos os testes de integração onde as unidades individuais são testadas como um grupo e os testes de ponta a ponta que testa todo o sistema.
Iniciando os testes de unidade
Vamos recordar os endpoints da nossa API para sabermos exatamente o que precisamos testar:
GET /Livros | Retorna todos os livros |
GET /Livros/{id} | Obtêm um livro pelo id |
POST /Livros | Adiciona um novo livro |
PUT /Livros/{id} | Atualiza um livro existente |
DELETE /Livros/{id} | Deleta um livro |
No xUnit precisamos decorar os métodos de teste com o atributo [Fact], que é usado pelo xUnit para marcar os métodos de testes. Além dos métodos de testes, também podemos ter vários métodos auxiliares na classe de teste.
Ao escrever testes
unitários, em geral seguimos o princípio AAA : Act,
Arrange e Assert (Organizar, Agir e Assertir):
Arrange - É aqui que você normalmente prepara tudo
para o teste, em outras palavras, prepara a cena para testar (criar os objetos e
configurá-los conforme necessário)
Act - É onde o método que estamos testando será
executado;
Assert - Esta é a parte final do teste em que
comparamos o que esperamos que aconteça com o resultado real da execução do
método de teste;
Os nomes dos métodos de teste devem ser tão descritivos quanto possível. Na
maioria dos casos, é possível nomear o método para que nem seja necessário ler o
código real para entender o que está sendo testado.
No exemplo, usamos a seguinte convenção de nomenclatura :
1
- A primeira parte do nome representa o nome do método HTTP que está sendo
testado;
2- A segunda parte do nome nos informa mais sobre o cenário de teste;
3- A última parte do nome é o resultado esperado;
Exemplo : GET_Livros_RetornaListaLivros
1- Testando o método GET que retorna todos os itens : GET_Livros_RetornaOKListaLivros
using ApiLivraria.Controllers; using ApiLivraria.Models; using ApiLivraria.Services; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using Xunit; namespace ApiLivraria.Tests; public class ApiLivrariaTest { LivrosController _controller; ILivroService _service; public ApiLivrariaTest() { _service = new LivroService(); _controller = new LivrosController(_service); }
[Fact]
//Assert
var lista = result.Result as OkObjectResult;
var listaLivros = lista.Value as List<Livro>; |
Neste código temos que :
1- Definimos as referências no construtor para o serviço LivroService() e para o controlador LivrosController() que tem como parâmetro o serviço.
A seguir vamos testar o primeiro endpoint GET que deve retornar uma lista de livros usando o método Ok().
Assim não temos que passar nenhum parâmetro em LivrosControllerTest pois o método Get não recebe parâmetros apenas retorna todos os livros.
Assim a definição em :
A primeira coisa que verificamos e se o tipo de resposta é um OkObjectResult, então, uma vez que sabemos que o endpoint da API retornou um objeto Ok, verificamos o tipo de resultado, e vemos se é uma lista de livros.
Então, ao final, verificamos o número de livros que foram devolvidos e assim testamos com sucesso o método Get do nosso Controller usando o método GET_Livros_RetornaOKListaLivros.
Acionando o menu Test -> Test Explorer no Visual Studio e executando o teste teremos o resultado abaixo:
2- Testando o método GET que retorna um livro pelo id : GET_Livro_RetornaOKListaLivros
No código omitimos a definição do serviço e do controlador e focamos apenas no código usado pelo método para testar a obtenção de um livro pelo seu Guid.
Aqui vamos usar o atributo [Theory] que indica que temos um teste parametrizado que é verdadeiro para um subconjunto de dados. Esses dados podem ser fornecidos de várias maneiras, mas o mais comum é com um atributo [InlineData]. Assim este atributo permite executar um método de teste várias vezes passando diferentes valores a cada vez como parâmetros.
Vamos passar dois valores de Guid : Um válido e que vai retornar o primeiro livro e outro inválido que vai retornar NotFound.
[Theory] [InlineData("ab2bd817-98cd-4cf3-a80a-53ea0cd9c200", "ab2bd817-98cd-4cf3-a80a-53ea0cd9c111")] public void GET_LivroGuid_RetornaOKLivro(string guid1, string guid2) { //Arrange var guidValido = new Guid(guid1); var guidInvalido = new Guid(guid2);
//Act
//Assert
//Precisamos checar o valor do
resultado para método OK
//Esperamos
retornar um livro
//Vamos verificar o valor |
Ao final estamos conferindo também se o título do livro confere com o título do primeiro livro que é o livro esperado para o GUID válido informado.
3- Testando o método POST que cria um novo livro : POST_Livro_CreatedAtLivro
Agora vamos criar um novo livro com dados completos e verificar o resultado que deve ser um CreatedAtActionResult e o valor e a seguir vamos testar a criação de um livro incompleto onde teremos um BadRequest com estado inválido.
[Fact] public void POST_Livro_CreatedAtLivro() { //Arrange var NovoLivro = new Livro() { Autor = "Macoratti", Titulo = "Meu Livro", };
//Act
//Assert
//valor do resultado
//verificar o valor do livro //OK RESULT TESTE termina
//BADREQUEST
e ERRO de MODELSTATE O test reinicia
//Act
//Assert |
Executando o teste teremos o resultado abaixo:
4- Testando o método DELETE que excluir um livro pelo GUID : DELETE_LivroGUID_OK
Agora iremos testar o método DELETE para excluir um livro pelo GUID.
Vamos informar dois guids, um válido e outro inválido usando os atributos [Theory] e {InlineData()].
A seguir vamos obter um NotFound para o guid inválido e assim o total de livros deverá continuar igual a 5.
Depois vamos excluir um livro com GUID válido e vamos obter OK e teremos um livro a menos no total.
[Theory] [InlineData("ab2bd817-98cd-4cf3-a80a-53ea0cd9c200", "ab2bd817-98cd-4cf3-a80a-53ea0cd9c111")] public void DELETE_LivroGUID_OK(string guid1, string guid2) { //Arrange var guidValido = new Guid(guid1); var guidInvalido = new Guid(guid2); //Act //Assert //Act //Assert |
Executando o teste teremos o resultado abaixo:
Concluímos assim os nossos testes de unidade que foram feitos de forma bem simples onde apresentamos alguns aspectos e usos do xUnit.
Pegue o projeto aqui: ApiLivraria.zip (sem referências)
"Mas agora,
morrendo para aquilo que antes nos prendia, fomos libertados da lei, para
que sirvamos conforme o novo modo do Espírito, e não segundo a velha forma
da lei escrita."
Romanos 7:6
Referências:
ASP .NET - Gerando QRCode com a API do Google
C# 9.0 - Instruções de nível superior
ASP.NET Core Web API - Apresentando API Analyzers
ASP.NET Core - Usando o token JWT com o Swagger
Gerando a documentação da Web API com Swagger