Exercício – fazer um teste de unidades a uma Função do Azure
O teste de unidades é uma parte fundamental de uma metodologia Ágil. O Visual Studio fornece o modelo de projeto de Teste. Utilize este modelo para criar os testes de unidades para as suas aplicações e pode aplicar a mesma técnica ao teste das Funções do Azure.
No cenário de sites online de relógios de luxo, sua equipe de desenvolvimento tem uma política para alcançar pelo menos 80% de cobertura de código em testes de unidade. Pretende implementar a mesma política para as Funções do Azure.
Aqui, você vê como usar a estrutura de teste com o Visual Studio para testar o xUnit
Azure Functions.
Criar um projeto de teste de unidades
A primeira etapa é criar um projeto que contenha seus testes de unidade e adicioná-lo à solução que contém seu Aplicativo de Função do Azure. Utilize os passos seguintes para criar um projeto de teste de unidades para testar a função WatchInfo.
No Visual Studio, na janela Solution Explorer (Explorador de Soluções), clique com o botão direito do rato na solução WatchPortalFunction, selecione Add (Adicionar) e, em seguida, selecione New Project (Novo Projeto).
Na janela Adicionar um novo projeto, role para baixo, selecione o modelo de ícone xUnit Test Project C#+ e selecione Avançar.
Será apresentada a janela Configure your new project (Configurar o novo projeto). No campo Project name (Nome do projeto) introduza WatchFunctionsTests. Além do campo Local , selecione o ícone de navegação e, em seguida, selecione a pasta WatchPortalFunction .
Selecione Seguinte. A janela Informações adicionais é exibida.
Em Target Framework. aceite o valor padrão do .NET 6.0 (suporte de longo prazo).
Selecione Criar.
Quando o projeto for adicionado, clique com o botão direito do mouse no projeto WatchFunctionTests na janela Gerenciador de Soluções e selecione Gerenciar Pacotes NuGet.
Na janela NuGet: WatchFunctionTests, selecione a guia Procurar. Na caixa Pesquisar, digite Microsoft.AspNetCore.Mvc. Selecione o pacote Microsoft.AspNetCore.Mvc e, em seguida, selecione Install (Instalar).
Nota
O projeto de teste cria um ambiente HTTP fictício. As classes necessárias para fazê-lo estão no pacote Microsoft.AspNetCore.Mvc.
Aguarde enquanto o pacote é instalado. Se a caixa de mensagem Preview Changes (Pré-visualizar Alterações) for apresentada, selecione OK. Na caixa de mensagem License Acceptance (Aceitação de Licença), selecione I Accept (Aceito).
Depois que o pacote for adicionado, na janela Gerenciador de Soluções, no projeto WatchFunctionsTests, clique com o botão direito do mouse no arquivo UnitTest1.cs e selecione Renomear. Altere o nome do ficheiro para WatchFunctionUnitTests.cs. Na caixa de mensagem que aparece, para mudar o nome de todas as referências de UnitTest1 para WatchFunctionUnitTests, selecione Yes (Sim).
Na janela Gerenciador de Soluções, no projeto WatchFunctionsTests, clique com o botão direito do mouse em Dependências e selecione Adicionar Referência de Projeto.
Na janela Reference Manager (Gestor de Referências), selecione o projeto WatchPortalFunction e selecione OK.
Adicionar testes de unidades para a função WatchInfo
Agora, pode adicionar testes de unidades ao projeto de teste. No cenário de relógios de luxo, quer certificar-se de que a função WatchInfo devolve sempre uma resposta OK quando um modelo é fornecido na cadeia de consulta de um pedido e uma resposta Bad se a cadeia de consulta estiver vazia ou não incluir o parâmetro model
.
Para verificar esse comportamento, você adiciona um par de testes de fato para o WatchFunctionsTests.
Na janela Gerenciador de Soluções , para exibir o WatchPortalFunction na janela de código, clique duas vezes no arquivo WatchFunctionUnitTests.cs .
Na parte superior do ficheiro, adicione as seguintes diretivas
using
à lista.using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Logging.Abstractions;
Altere o nome do método Test1 para TestWatchFunctionSuccess.
No corpo do método TestWatchFunctionSuccess, adicione o seguinte código. Esta instrução cria um contexto de HTTP fictício e um pedido HTTP. O pedido inclui uma cadeia de consulta que inclui o parâmetro
model
, que está definido comoabc
.var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "model", queryStringValue } } ) };
Adicione a seguinte instrução ao método. Esta instrução cria um logger fictício.
var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
Adicione o seguinte código ao método. Estas instruções invocam a função WatchInfo, transmitindo o pedido e o logger fictícios como parâmetros.
var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait();
Adicione o seguinte código ao método. Este código verifica se a resposta da função está correta. Neste caso, a função deve retornar uma resposta OK , contendo os dados esperados no corpo.
// Check that the response is an "OK" response Assert.IsAssignableFrom<OkObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (OkObjectResult)response.Result; dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 }; string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}"; Assert.Equal(watchInfo, result.Value);
O método completo deve ter a seguinte aparência.
[Fact] public void TestWatchFunctionSuccess() { var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "model", queryStringValue } } ) }; var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "OK" response Assert.IsAssignableFrom<OkObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (OkObjectResult)response.Result; dynamic watchinfo = new { Manufacturer = "abc", CaseType = "Solid", Bezel = "Titanium", Dial = "Roman", CaseFinish = "Silver", Jewels = 15 }; string watchInfo = $"Watch Details: {watchinfo.Manufacturer}, {watchinfo.CaseType}, {watchinfo.Bezel}, {watchinfo.Dial}, {watchinfo.CaseFinish}, {watchinfo.Jewels}"; Assert.Equal(watchInfo, result.Value); }
Adicione mais dois métodos com os nomes TestWatchFunctionFailureNoQueryString e TestWatchFunctionFailureNoModel. O método TestWatchFunctionFailureNoQueryString verifica se a função WatchInfo falha mas termina corretamente, caso não seja indicada uma cadeia de consulta. O método TestWatchFunctionFailureNoModel verifica a mesma falha se a função transmitir uma cadeia de consulta que não contenha um parâmetro de modelo.
[Fact] public void TestWatchFunctionFailureNoQueryString() { var request = new DefaultHttpRequest(new DefaultHttpContext()); var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "Bad" response Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (BadRequestObjectResult)response.Result; Assert.Equal("Please provide a watch model in the query string", result.Value); } [Fact] public void TestWatchFunctionFailureNoModel() { var queryStringValue = "abc"; var request = new DefaultHttpRequest(new DefaultHttpContext()) { Query = new QueryCollection ( new System.Collections.Generic.Dictionary<string, StringValues>() { { "not-model", queryStringValue } } ) }; var logger = NullLoggerFactory.Instance.CreateLogger("Null Logger"); var response = WatchPortalFunction.WatchInfo.Run(request, logger); response.Wait(); // Check that the response is an "Bad" response Assert.IsAssignableFrom<BadRequestObjectResult>(response.Result); // Check that the contents of the response are the expected contents var result = (BadRequestObjectResult)response.Result; Assert.Equal("Please provide a watch model in the query string", result.Value); }
Executar os testes
Na barra de menu superior, em Testar, selecione Executar todos os testes.
Na janela Test Explorer (Explorador de Testes), os três testes devem ser concluídos com êxito.
Na janela Solution Explorer (Explorador de Soluções), sob o projeto WatchPortalFunction, faça duplo clique no WatchInfo.cs para apresentá-lo no editor de código.
Localize o seguinte código.
// Retrieve the model id from the query string string model = req.Query["model"];
Altere a instrução que define a variável
model
da seguinte forma. Essa alteração simula o desenvolvedor cometendo um erro no código.string model = req.Query["modelll"];
Na barra de menu superior, em Testar, selecione Executar todos os testes. Desta vez, o teste TestWatchFunctionSuccess deverá falhar. Essa falha ocorre porque a função WatchInfo não encontra o parâmetro nomeado
modelll
na cadeia de caracteres de consulta e, portanto, a função retorna uma resposta incorreta .
Nesta unidade, você viu como criar um projeto de teste de unidade e implementar testes de unidade para uma Função do Azure.