Testes de APIs REST com .NET 5, xUnit, Refit e Fluent Assertions

Renato Groffe
6 min readJan 18, 2021

--

Inúmeras são as abordagens para a implementação de testes automatizados, com a codificação de testes de unidade e de interfaces Web representando as práticas mais comuns. As plataformas de desenvolvimento mais populares no mercado oferecem um amplo suporte aos testes de aplicações, com numerosos frameworks e ferramentas simplificando em muito a vida de Desenvolvedores e profissionais da área de Qualidade de Software.

APIs REST constituem atualmente elementos de fundamental importância nos mais variados tipos de arquiteturas, porém em muitos casos os testes das mesmas acabam sendo relegados à simples conferência via browser ou por meio de ferramentas com uma interface gráfica como Postman. Automatizar estas checagens torna possível reexecutar com velocidade validações importantes a qualquer momento, bem como inserir num processo de build/deployment automatizados validações que garantam o correto funcionamento de tais APIs.

São muitos os casos de equívocos e implementações descuidadas envolvendo APIs REST, sobretudo no que se refere ao retorno de códigos HTTP que indiquem corretamente o resultado de uma operação (quem nunca se deparou com uma API que retorna sempre o código 200 - OK, mesmo em situações de falha?). A importância nesses casos de testes automatizados está justamente em não apenas garantir a validade dessas APIs em cenários de sucesso, como também assegurar que erros sejam verificados. Com tudo isto seremos então capazes de evitar anomalias no funcionamento de aplicações que dependam de APIs REST.

Neste novo artigo demonstrarei como implementar testes automatizados de APIs REST, valendo-se para isto do .NET 5 e dos frameworks xUnit, Refit e Fluent Assertions.

E aproveito este espaço também para um convite…

Confira nesta segunda 18/01/2021 a partir das 21:00 - horário de Brasília - mais um evento ONLINE e GRATUITO no Canal .NET. Desta vez será abordada a implementação e configuração de testes automatizados de software (e em quais momentos utilizamos cada um dos tipos de testes) utilizando Azure DevOps e GitHub Actions.

Ao longo da live será abordado o uso de tecnologias como .NET Core, ASP.NET Core, .NET 5, Docker, Kubernetes, JMeter, xUnit, SpecFlow, Selenium, Visual Studio, Slack, Azure Functions e outros serviços do Microsoft Azure.

Para efetuar sua inscrição acesse:

https://bit.ly/live-automacao-testes-pt2

Implementando testes de APIs REST

A API REST que será validada e o projeto com os testes estão no seguinte repositório do GitHub:

.NET 5 + xUnit + Fluent Assertions + HttpClient + Refit + API REST para conversão de temperaturas (em ASP.NET Core)

De forma a simular as situações de erro deixei comentada na classe ConversorTemperaturasController do projeto APITemperatura uma validação que retornaria o erro 400 (Bad Request), indicando valores de temperatura inválidos:

A classe Temperatura em APITemperatura também foi adaptada, com o arredondamento dos cálculos de conversão de temperaturas em Fahrenheit para Celsius e Kelvin desativados. Além disso, uma exceção será gerada para temperaturas inválidas (resultando num erro 500 - Internal Server Error):

O projeto APITemperatura.Testes foi criado com base no template do .NET 5 para testes com xUnit. Adicionei ainda ao mesmo os packages:

  • FluentAssertions, alternativa que simplifica a escrita de validações e possibilita até mesmo a definição de mensagens customizadas para falhas na execução de testes;
  • Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json e Microsoft.Extensions.Options.ConfigurationExtensions, a fim de permitir o uso de um arquivo appsettings.json com configurações e que variáveis de ambiente possam substituir o que constar no mesmo (algo útil em se tratando de ferramentas de automação como Azure DevOps e GitHub Actions);
  • Refit, biblioteca que simplifica em muito o consumo de APIs REST através da geração de clients baseados em interfaces (evitando assim muito do código que seria escrito ao se optar pela classe HttpClient).

No arquivo appsettings.json está o item de configuração UrlWebAppTestes, o qual indica o endereço-base/site que será utilizado para acessar a API de conversão de temperaturas (passível de ser substituído pelo conteúdo de uma variável de ambiente):

A classe Temperatura contém a representação dos dados devolvidos pela API de conversão de temperaturas:

A interface IConversorTemperaturasAPI define a estrutura do client de consumo da API a ser gerado pelo Refit:

  • O método GetAsync foi marcado com o atributo Get, indicando que o mesmo irá enviar requisições HTTP GET à API de conversão;
  • No atributo Get podemos definir a rota de acesso à API REST, incluindo eventuais parâmetros (como no caso de vlFahrenheit). Outros verbos HTTP como Put e Post são representados por atributos de mesmo nome;
  • O retorno de métodos em uma interface criada para o Refit sempre será baseado em Task, já que esta biblioteca se baseia em implementações assíncronas;
  • Poderíamos simplesmente retornar uma instância de Temperatura vinculada a Task, mas foi optado aqui pelo uso em conjunto do tipo ApiResponse. Esta opção oferecida pelo Refit permite tanto o acesso aos dados de uma resposta, como também qual o código de retorno HTTP e eventuais informações de erro;
  • As diferentes estruturas oferecidas pelo Refit se encontram num namespace com o mesmo desta biblioteca.

No tipo ConversorTemperaturasTests foram escritos os diferentes testes:

  • O método TestarConversoesValidas verificará os retornos gerados pela conversão de temperaturas válidas na escala Fahrenheit. Inicialmente isto envolverá a checagem do StatusCode (200 - OK) com os métodos Should e Be do Fluent Assertions. Na sequência 2 verificações também empregando recursos do Fluent Assertions validarão os cálculos realizados nas escalas Celsius e Kelvin;
  • Já o método TestarFalhas checará se ao informar temperaturas inválidas à API será devolvido o código 400 - Bad Request;
  • No construtor de ConversorTemperaturasTests o objeto configuration está sendo gerado, de forma a carregar o valor de UrlWebAppTestes definido em appsettings.json. Uma variável no ambiente em que o projeto de testes for executado pode possuir também como nome UrlWebAppTestes, com este valor tendo precedência sobre aquele que se encontra em appsettings.json (característica muito útil em soluções de automação);
  • Nesse construtor também está sendo gerado um client baseado na interface IConversorTemperaturasAPI, com isto acontecendo por meio da classe RestService do Refit. A grande vantagem do Refit está justamente em criar objetos dinamicamente apontando para uma interface, sem todo o trabalho de codificação que envolveria a utilização da classe HttpClient.

Ao executar esses testes no Visual Studio 2019 falhas acontecerão em TestarConversoesValidas, devido à falta de arredondamento nas conversões:

E em TestarFalhas (o esperado como retorno era 400 - Bad Request, mas não 500 - Internal Server Error):

Corrigindo a classe Temperatura do projeto APITemperatura:

E o tipo ConversorTemperaturasController:

Todos os testes finalmente passarão:

Demonstrei também este exemplo na prática em uma live recente do Canal .NET que pode ser assistida gratuitamente no YouTube:

E termino este post com outro convite…

Que tal participar do treinamento online pioneiro no Brasil sobre GitHub Actions e promovido pelo Azure na Prática, agora com aulas gravadas e uma primeira sessão ao vivo com resolução de dúvidas durante o dia 23/01/2021 (sábado)?

Acompanhe com comodidade e a qualquer tempo os diversos módulos deste treinamento, em que serão cobertas boas práticas + estratégias de build/testes/deployment e o uso desta solução de automação com tecnologias como Docker, Kubernetes, Azure App Service, Azure Functions e outros serviços da nuvem Microsoft!

Acesse então o link a seguir para efetuar sua inscrição com um desconto especial de R$ 100,00 (inclui certificado e grupo para resolução de dúvidas durante e após o curso):

https://bit.ly/anp-githubactions-desc-100-blog-groffe

--

--

Renato Groffe

Microsoft Most Valuable Professional (MVP), Multi-Plataform Technical Audience Contributor (MTAC), Software Engineer, Technical Writer and Speaker