consumo de dados de uma API. Entretanto o ponto de maior orgulho desta biblioteca é a facilidade em testar as requisições criadas com ela.
Testar classes que fazem requisições HTTP pode ser um ponto complexo do projeto. Ele precisa ser desenvolvido de forma que aceite um Mock ou fazer uso de uma API de testes.
Uma API de testes pode ser uma boa escolha, mas caso ocorra algo com a mesma, os testes do projeto irão falhar. Enquanto o problema com a API não for resolvido, estes testes não poderão ser realizados.
Então, o mais comum é o uso de Mock, que deve ser implementado de acordo com a biblioteca de requisições implementada, já que a classe HttpClient
não pode ser “mockada”. Ela não define interfaces que facilitariam este processo.
Dentre as bibliotecas de requisição que permitem o uso de Mock, a Flurl é a que torna este processo o mais transparente e simples.
Para exemplificar, serão implementados testes de unidade no projeto apresentado no meu artigo anterior. Nele vimos a implementação do Flurl na camada repository do projeto, assim, os testes de unidade mostrados aqui serão realizados apenas nesta camada.
Os testes podem ser feito graças a classe HttpTest
da biblioteca. Recomenda-se que ela seja declarada em um bloco using
:
using (var httpTest = new HttpTest()) {
// Realizar as requisições aqui
}
Desta forma, todas as requisições realizadas dentro deste bloco serão interceptadas pela classe e com isso, poderão ser “mockadas”:
public async Task TestListProducts()
{
var repository = new ProductRepository();
using (var httpTest = new HttpTest()) {
// arrange
httpTest.RespondWith("[{\"id\":\"12d3d23\",\"name\":\"Mouse\", \"quantity\":10, \"price\": 99.9}, {\"id\":\"213drwa3\",\"name\":\"Teclado\", \"quantity\":20, \"price\": 149.9}]");
// act
await repository.FindAll();
// assert
httpTest
.ShouldHaveCalled("http://localhost:3002/api/products")
.WithVerb(HttpMethod.Get);
}
}
Acima, é definido o mock:
httpTest.RespondWith("[{\"id\":\"12d3d23\",\"name\":\"Mouse\", \"quantity\":10, \"price\": 99.9}, {\"id\":\"213drwa3\",\"name\":\"Teclado\", \"quantity\":20, \"price\": 149.9}]");
Ou seja, não importa qual requisição, será retornado este conteúdo.
Em seguida a requisição é realizada:
await repository.FindAll();
E é verificado se ela foi feita para a API via GET:
httpTest
.ShouldHaveCalled("http://localhost:3002/api/products")
.WithVerb(HttpMethod.Get);
Ao executar o teste, ele irá passar:
No exemplo anterior todas as requisições realizadas serão interceptadas pela classe HttpTest
. Entretanto, é possível refinar isso:
public async Task TestCreateProducts()
{
var repository = new ProductRepository();
using (var httpTest = new HttpTest()) {
// arrange
httpTest
.ForCallsTo("http://localhost:3002/*", "https://api.com/*")
.WithVerb(HttpMethod.Post)
.RespondWith("[{\"id\":\"12d3d23\",\"name\":\"Mouse\", \"quantity\":10, \"price\": 99.9}", 201);
var product = new Product {
Name = "Mouse",
Quantity = 10,
Price = 99.9
};
// act
await repository.Add(product);
// assert
httpTest
.ShouldHaveCalled("*/api/products")
.WithRequestBody("{\"Id\":*,\"Name\":\"Mouse\",\"Quantity\":10,\"Price\":99.9}")
.WithVerb(HttpMethod.Post);
}
}
Note que é definido as APIs que serão interceptadas e o verbo HTTP:
httpTest
.ForCallsTo("*localhost:3002/*", "*api.*.com/*")
.WithVerb(HttpMethod.Post)
Qualquer requisição que não se enquadre nestes critérios será ignorada pela HttpTest
.
No assert, se verifica apenas o endpoint:
httpTest
.ShouldHaveCalled("*/api/products")
Não é necessário informar o servidor, porque os aceitos já estão definidos no critério especificado. Também note que é utilizado curingas (*
). Eles podem ser implementados nos parâmetros de todos os métodos da classe.
Caso o teste seja executado, este segundo também passará:
Adicionar testes em um projeto é uma boa prática que todos devem adotar. Ao se trabalhar com requisições, este processo pode ser facilitado ao adotar a biblioteca Flurl. Assim, caso esteja trabalhando com requisições e necessite implementar testes, não deixe de verificar esta biblioteca.
Neste artigo não foram abordados todos os métodos da classe HttpTest
. Como vários são úteis, não deixe de vê-los na documentação da mesma.
Então é isso, por hoje é só :)
Instrutor, nerd, cinéfilo e desenvolvedor nas horas vagas. Graduado em Ciências da Computação pela Universidade Metodista de São Paulo.
Todos os artigosAprenda como gerar APIs clientes com a global tool Microsoft.dotnet-openapi.
Veja como consumir dados de uma API no C#, utilizando a biblioteca Flurl.
Conheça os novos tipos de dados introduzidos no C# 9.0, os inteiros nativos e os novos recursos da i...
Dando continuidade ao nosso estudo do C# 9.0, neste artigo veremos dois novos recursos dele: Program...
Já estamos no C# 9.0, a nova versão lançada no .NET Conf 2020 trouxe uma série de novos recursos, ve...
Neste artigo veremos como instalar o C# nos sistemas Windows, Linux e MacOS e também veremos como es...
Quer iniciar seus estudos em C# (C Sharp) e não sabe por onde começar? Veja o que preparamos pra voc...
Aprenda o que são e como funcionarão as tuplas no C# 7.
Conheça a biblioteca AutoMapper e aprenda como implementá-la em uma aplicação C#.
Testes unitários ajudam a garantir a qualidade de uma aplicação. Uma forma de garantir isso no C# é...
Testes unitários ajudam a garantir a qualidade de uma aplicação. Uma forma de garantir isso no C# é...
Testes unitários ajudam a garantir a qualidade de uma aplicação. No C# temos a biblioteca NUnit. Vej...