Desenvolver o Azure Functions usando o Visual Studio

O Visual Studio permite que você desenvolva, teste e implante funções da biblioteca de classes C# no Azure. Se esta for sua primeira experiência com o Azure Functions, confira Uma introdução ao Azure Functions.

O Visual Studio oferece os seguintes benefícios quando você desenvolve suas funções:

  • Editar, criar e executar funções em seu computador de desenvolvimento local.
  • Publique seu projeto do Azure Functions diretamente no Azure e crie recursos do Azure conforme necessário.
  • Use atributos C# para declarar associações de função diretamente no código C#.
  • Desenvolver e implantar funções de pré-compiladas C#. Funções pré-compiladas fornecem um desempenho de inicialização a frio melhor que funções baseadas em script C#.
  • Codificar suas funções em C# tendo todos os benefícios de desenvolvimento do Visual Studio.

Este artigo fornece detalhes sobre como usar o Visual Studio para desenvolver funções de biblioteca de classes C# e publicá-las no Azure. Antes de ler este artigo, considere concluir o guia início rápido das funções para o Visual Studio.

Os procedimentos e exemplos mostrados são para o Visual Studio 2022, a não ser que haja alguma indicação contrária. Para obter mais informações sobre as versões do Visual Studio 2022, confira as notas sobre a versão ou as notas sobre a versão prévia.

Pré-requisitos

  • Ferramentas do Azure Functions. Para adicionar as Ferramentas do Azure Functions, inclua a carga de trabalho de desenvolvimento do Azure na instalação do Visual Studio. Se você estiver usando o Visual Studio 2017, talvez seja necessário seguir algumas etapas extras de instalação.

  • Outros recursos necessários, como uma conta de armazenamento do Azure, são criados em sua assinatura durante o processo de publicação.

  • Caso você não tenha uma assinatura do Azure, crie uma conta gratuita do Azure antes de começar.

Criar um projeto do Azure Functions

O modelo de projeto do Azure Functions no Visual Studio cria um projeto de biblioteca de classes C# que você pode publicar em um aplicativo de funções no Azure. Você pode usar um aplicativo de funções para agrupar funções como uma unidade lógica para facilitar o gerenciamento, a implantação, o dimensionamento e o compartilhamento de recursos.

  1. No menu do Visual Studio, selecione Arquivo>Novo>Projeto.

  2. Em Criar um projeto, insira funções na caixa de pesquisa, escolha o modelo Azure Functions e, em seguida, selecione Próximo.

  3. Em Configurar seu novo projeto, insira um Nome de projeto para seu projeto e, em seguida, selecione Criar. O nome do aplicativo de funções deve ser válido como um namespace do C# e, portanto, não use outros caracteres não alfanuméricos, hífens ou sublinhados.

  4. Para as configurações de Criar um aplicativo do Azure Functions, use os valores da tabela a seguir:

    Configuração Valor Descrição
    Versão do .NET .NET 6 Isolado Esse valor cria um projeto de função que é executado em um processo de trabalho isolado. Para obter mais informações, consulte Visão geral de versões do Azure Functions runtime.
    Modelo de função Gatilho HTTP Esse valor cria uma função acionada por uma solicitação HTTP.
    Conta de armazenamento (AzureWebJobsStorage) Emulador de armazenamento Como um aplicativo de funções no Azure requer uma conta de armazenamento, ela será atribuída ou criada quando você publicar seu projeto no Azure. Um gatilho HTTP não usa uma cadeia de conexão da conta do Armazenamento do Azure; todos os outros tipos de gatilho exigem uma cadeia de conexão válida da conta do Armazenamento do Azure.
    Nível de autorização Anônimo A função criada pode ser acionada por qualquer cliente sem fornecer uma chave. Essa configuração de autorização torna fácil testar a nova função. Para obter mais informações sobre chaves e autorização, consulte Chaves de autorização e associações HTTP e webhook.

    Azure Functions project settings

    Verifique se você definiu o Nível de autorização como Anônimo. Se você escolher o nível padrão da Função, será necessário que você apresente a chave da função em solicitações para acessar seu ponto de extremidade da função.

  5. Selecione Criar para criar o projeto de função e a função de gatilho HTTP.

Depois de criar um projeto do Azure Functions, o modelo de projeto cria um projeto C#, instala o pacote NuGet Microsoft.NET.Sdk.Functions e define a estrutura de destino. O novo projeto contém os seguintes arquivos:

  • host.json: Permite que você configure o host do Functions. Essas configurações se aplicam para execução local e no Azure. Para obter mais informações, consulte a referência para host.json.

  • local.Settings.json: Mantém as configurações usadas ao executar as funções localmente. Essas configurações não são usadas quando estão em execução no Azure. Para obter mais informações, confira Arquivo de configurações local.

    Importante

    Como o arquivo local.settings.json pode conter segredos, você precisa excluí-lo do controle do código-fonte do projeto. Verifique se a configuração Copiar para o Diretório de Saída desse arquivo está definida como Copiar se for mais recente.

Para saber mais, confira Projeto de biblioteca de classe de funções.

Trabalhe com as configurações do aplicativo localmente

Ao executar em um aplicativo de funções no Azure, as configurações exigidas por suas funções são armazenadas com segurança nas configurações do aplicativo. Durante o desenvolvimento local, essas configurações são adicionadas à coleção Values no arquivo local.settings.json. O arquivo local.settings.json também armazena as configurações usadas pelas ferramentas de desenvolvimento locais.

Os itens da Values coleção no arquivo local.settings.json do seu projeto destinam-se a espelhar itens nas configurações do aplicativo do seu aplicativo de funções no Azure.

O Visual Studio não carrega automaticamente as configurações em local.settings.json quando você publica o projeto. Para que essas configurações também existam em seu aplicativo de funções no Azure, carregue-as depois de publicar seu projeto. Para obter mais informações, confira Configurações do aplicativo de funções. Os valores em uma coleção ConnectionStrings nunca são publicados.

Seu código também pode ler os valores de configurações do aplicativo de funções como variáveis de ambiente. Para obter mais informações, confira Variáveis de ambiente.

Configurar seu projeto para desenvolvimento local

O runtime do Functions usa internamente uma conta de Armazenamento do Azure. Para todos os tipos de gatilhos diferentes de HTTP e webhooks, defina a chave Values.AzureWebJobsStorage como uma cadeia de conexão de conta de Armazenamento do Azure válida. O aplicativo de funções também pode usar o Emulador Azurite para a configuração de conexão AzureWebJobsStorage exigida pelo projeto. Para usar o emulador, defina o valor de AzureWebJobsStorage como UseDevelopmentStorage=true. Altere essa configuração para uma cadeia de conexão de conta de armazenamento antes da implantação. Para obter mais informações, confira Emulador de armazenamento local.

Para definir a cadeia de conexão da conta de armazenamento:

  1. No portal do Azure, navegue até sua conta de armazenamento.

  2. Na guia Chaves de acesso, abaixo de Segurança + rede, copie a Cadeia de conexão de key1.

  3. Em seu projeto, abra o arquivo local.settings.json e defina o valor da chave AzureWebJobsStorage na cadeia de conexão que você copiou.

  4. Repita a etapa anterior para adicionar as chaves exclusivas para a matriz de Values para todas as outras conexões necessárias para as suas funções.

Adicionar uma função ao projeto

Nas funções da biblioteca de classes C#, as associações usadas pela função são definidas aplicando atributos no código. Quando você cria seus gatilhos de função com base nos modelos fornecidos, os atributos de gatilho são aplicados para você.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e selecione Adicionar>Novo Item.

  2. Selecione Função do Azure, insira um Nome para a classe e escolha Adicionar.

  3. Escolha o gatilho, defina as propriedades de associação e clique em Adicionar. O exemplo a seguir mostra as configurações para criar uma função de gatilho de armazenamento de filas.

    Create a Queue storage trigger function

    Depois, será solicitado que você escolha entre o emulador de armazenamento Azurite ou referencie uma conta de armazenamento do Azure provisionada.

    Este exemplo de gatilho usa uma cadeia de conexão com uma chave chamada QueueStorage. Essa chave, armazenada no arquivo local.settings.json, faz referência ao emulador Azurite ou a uma conta de armazenamento do Azure.

  4. Examine a classe recém-adicionada. Você verá um método Run() estático atribuído com o atributo FunctionName. Esse atributo indica que o método é o ponto de entrada para a função.

    Por exemplo, a seguinte classe C# representa uma função básica de gatilho de armazenamento de filas:

    using System;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp1
    {
        public static class Function1
        {
            [FunctionName("QueueTriggerCSharp")]
            public static void Run([QueueTrigger("myqueue-items", 
                Connection = "QueueStorage")]string myQueueItem, ILogger log)
            {
                log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
            }
        }
    }
    

Um atributo específico de associação é aplicado a cada parâmetro de associação fornecido ao método do ponto de entrada. O atributo utiliza as informações de associação como parâmetros. No exemplo anterior, o primeiro parâmetro tem um atributo QueueTrigger aplicado, que indica a função de gatilho de armazenamento de filas. O nome da fila e o nome de configuração da cadeia de conexão são passadas como parâmetros ao atributo QueueTrigger. Para obter mais informações, veja Associações do armazenamento de Fila do Azure para o Azure Functions.

Use o procedimento acima para adicionar mais funções a seu projeto de aplicativo de funções. Cada função no projeto pode ter um gatilho diferente, mas uma função deve ter apenas um gatilho. Para obter mais informações, consulte Gatilhos e conceitos de associações do Azure Functions.

Adicionar associações

Assim como acontece com gatilhos, as associações de entrada e saída são adicionadas à sua função como atributos de associação. Adicione associações a uma função da seguinte maneira:

  1. Verifique se você configurou o projeto para desenvolvimento local.

  2. Adicione o pacote de extensão NuGet apropriado para a associação específica encontrando os requisitos de pacote NuGet específicos da associação no artigo de referência para a associação. Por exemplo, encontre os requisitos do pacote para o gatilho dos Hubs de Eventos no artigo de referência da associação dos Hubs de Eventos.

  3. Use o seguinte comando no Console do Gerenciador de Pacotes para instalar um pacote específico:

    Install-Package Microsoft.Azure.Functions.Worker.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
    

    Neste exemplo, substitua <BINDING_TYPE> pelo nome específico da extensão de ligação e <TARGET_VERSION> por uma versão específica do pacote, tal como 3.0.0-beta5. As versões válidas são listadas nas páginas de pacote individuais NuGet.org. As versões principais que correspondem ao Runtime do Functions 1.x ou 2.x são especificadas no artigo de referência para a associação.

  4. Se houver configurações de aplicativo exigidas pela associação, adicione-as à coleção Values no arquivo de configuração local.

    A função usa esses valores quando ele é executado localmente. Quando a função é executada no aplicativo de funções no Azure, ela usa configurações do aplicativo de funções.

  5. Adicione o atributo de associação apropriado para a assinatura do método. No exemplo a seguir, uma mensagem da fila dispara a função e a associação de saída cria uma nova mensagem de fila com o mesmo texto em uma fila diferente.

    public static class SimpleExampleWithOutput
    {
        [FunctionName("CopyQueueMessage")]
        public static void Run(
            [QueueTrigger("myqueue-items-source", Connection = "AzureWebJobsStorage")] string myQueueItem, 
            [Queue("myqueue-items-destination", Connection = "AzureWebJobsStorage")] out string myQueueItemCopy,
            ILogger log)
        {
            log.LogInformation($"CopyQueueMessage function processed: {myQueueItem}");
            myQueueItemCopy = myQueueItem;
        }
    }
    

    A conexão com o Armazenamento de filas é obtida na configuração AzureWebJobsStorage. Para saber mais, confira o artigo de referência da associação específica.

Para ver uma lista completa das vinculações compatíveis com o Functions, confira Vinculações compatíveis.

Executar funções localmente

As Ferramentas Principais do Azure Functions permitem executar o projeto do Azure Functions no seu computador de desenvolvimento local. Quando você pressiona F5 para depurar um projeto do Functions, o host local do Functions (func.exe) começa a escutar uma porta local (geralmente, a 7071). Todos os pontos de extremidade de função que podem ser chamados são gravados na saída, e você pode usar esses pontos de extremidade para testar as funções. Para obter mais informações, confira Trabalhar com o Azure Functions Core Tools. É solicitado que você instale essas ferramentas na primeira vez em que inicia uma função no Visual Studio.

Para iniciar sua função no Visual Studio no modo de depuração:

  1. Pressione F5. Se solicitado, aceite a solicitação do Visual Studio para baixar e instalar as ferramentas principais (CLI) do Azure Functions. Além disso, talvez seja necessário habilitar uma exceção de firewall para que as ferramentas possam manipular solicitações HTTP.

  2. Com o projeto em execução, teste seu código da mesma forma que você testaria uma função implantada.

    Quando você executa o Visual Studio em modo de depuração, os pontos de interrupção são atingidos conforme o esperado.

Para ver um cenário de teste mais detalhado usando o Visual Studio, confira Funções de teste.

Publicar no Azure

Quando você faz uma publicação por meio do Visual Studio, ele usa um destes dois métodos de implantação:

Use as etapas a seguir para publicar seu projeto para um aplicativo de funções no Azure.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no nome do projeto e selecione Publicar. Em Destino, selecione Azure e Avançar.

    Screenshot of publish window.

  2. Escolha Aplicativo de Funções do Azure (Windows) em Destino específico, o que criará um aplicativo de funções executado no Windows, e selecione Avançar.

    Screenshot of publish window with specific target.

  3. Em Instância de Função, escolha Criar uma Função do Azure…

    Screenshot of create a new function app instance.

  4. Crie uma instância usando os valores especificados nesta tabela:

    Configuração Valor Descrição
    Nome Nome globalmente exclusivo Nome que identifica seu novo aplicativo de funções de forma exclusiva. Aceite esse nome ou insira um novo nome. Os caracteres válidos são: a-z, 0-9 e -.
    Assinatura Sua assinatura A assinatura do Azure a utilizar. Aceite esta assinatura ou selecione uma nova na lista suspensa.
    Grupo de recursos Nome do seu grupo de recursos O grupo de recursos no qual você deseja criar o aplicativo de funções. Selecione um grupo de recursos existente na lista suspensa ou escolha Novo para criar um grupo de recursos.
    Tipo de Plano Consumo Quando você publica seu projeto em um aplicativo de funções executado em um Plano de consumo, você paga apenas pelas execuções do seu aplicativo de funções. Outros planos de hospedagem incorrem em custos mais altos.
    Localidade Local do serviço de aplicativo Escolha um Local em uma região perto de você ou de outros serviços acessados pelas suas funções.
    Armazenamento do Azure Conta de armazenamento para uso geral Uma conta de armazenamento do Azure é requerida pelo runtime do Functions. Selecione Novo para configurar uma conta de armazenamento para uso geral. Você também pode escolher uma conta existente que atenda aos requisitos da conta de armazenamento.

    Screenshot of Create App Service dialog.

  5. Selecione Criar para criar um aplicativo de funções e recursos relacionados no Azure. O status da criação do recurso é mostrado no canto inferior esquerdo da janela.

  6. Na Instância do Functions, verifique se a opção Executar no arquivo de pacote está marcada. Seu aplicativo de funções é implantado usando a Implantação de Zip com o modo Run-From-Package habilitado. A Implantação de Zip é o método de implantação recomendado para seu projeto de funções, pois ele resulta em um melhor desempenho.

    Screenshot of Finish profile creation.

  7. Selecione Concluir e, na página Publicar, selecione Publicar para implantar o pacote que contém os arquivos do projeto no seu novo aplicativo de funções no Azure.

    Concluída a implantação, a URL raiz do aplicativo de funções no Azure é mostrada na guia Publicar.

  8. Na guia Publicar, na seção Hospedagem, escolha Abrir no portal do Azure. O novo recurso de aplicativo de funções do Azure é aberto no portal do Azure.

    Screenshot of Publish success message.

Configurações do aplicativo de funções

O Visual Studio não carrega essas configurações automaticamente quando você publica o projeto. As configurações adicionadas a local.settings.json também precisam ser adicionadas ao aplicativo de funções no Azure.

A maneira mais fácil de carregar as configurações necessárias para o aplicativo de funções no Azure é expandir os três pontos ao lado da seção Hospedagem e clicar no link Gerenciar configurações do Serviço de Aplicativo do Azure que aparece depois que você publica o projeto com êxito.

Settings in Publish window

Selecionar esse link exibe a caixa de diálogo Configurações de aplicativo para o aplicativo de função, onde você pode adicionar novas configurações do aplicativo ou modificar as existentes.

Application settings

Local exibe um valor de configuração no arquivo local.settings.json e Remoto exibe uma configuração atual no aplicativo de funções no Azure. Escolha Adicionar configuração para criar uma nova configuração de aplicativo. Use o link Inserir valor do local para copiar um valor de configuração para o campo Remoto. As alterações pendentes serão gravadas no arquivo de configurações local e no aplicativo de funções quando você selecionar OK.

Observação

Por padrão, o check-in do arquivo local.settings.json não é feito no controle do código-fonte. Isso significa que, se você clonar um projeto local do Functions do controle do código-fonte, o projeto não terá um arquivo local.settings.json. Nesse caso, você precisa criar manualmente o local.settings.json arquivo na raiz do projeto para que a caixa de diálogo Configurações do aplicativo funcione conforme o esperado.

Você também pode gerenciar as configurações de aplicativo em um desses outros modos:

Depuração remota

Para depurar seu aplicativo de funções remotamente, você precisa publicar uma configuração de depuração do seu projeto. Você também precisa habilitar a depuração remota em seu aplicativo de funções no Azure.

Esta seção pressupõe que você já publicou em seu aplicativo de funções usando uma configuração de versão.

Considerações de depuração remota

  • A depuração remota não é recomendada em um serviço de produção.
  • Se você tiver a depuração Apenas Meu Código habilitada, desabilite-a.
  • Evite paradas longas em pontos de interrupção durante a depuração remota. O Azure trata um processo parado por mais de alguns minutos como um processo sem resposta e o desliga.
  • Enquanto você está depurando, o servidor está enviando dados para o Visual Studio, o que pode afetar os encargos de largura de banda. Para obter informações sobre as taxas de largura de banda, consulte Preço do Azure.
  • A depuração remota é desabilitada automaticamente em seu aplicativo de funções após 48 horas. Após 48 horas, você precisará reabilitar a depuração remota.

Anexar o depurador

A maneira como você anexa o depurador depende do modo de execução. Ao depurar um aplicativo de processo de trabalho isolado, você precisa anexar o depurador remoto a um processo .NET separado e várias outras etapas de configuração são necessárias.

Quando terminar, você deve desabilitar a depuração remota.

Para anexar um depurador remoto a um aplicativo de funções em execução em processo separado do host do Functions:

  1. Na guia Publicar, selecione as reticências (...) na seção Hosting e escolha Baixar perfil de publicação. Essa ação baixa uma cópia do perfil de publicação e abre o local de download. Você precisa desse arquivo, que contém as credenciais usadas a serem anexadas ao processo de trabalho isolado em execução no Azure.

    Cuidado

    O arquivo .publishsettings contém suas credenciais (sem codificação) usadas para administrar seu aplicativo de funções. A prática recomendada de segurança para esse arquivo é armazená-lo temporariamente fora dos diretórios de origem (por exemplo, na pasta Libraries\Documents) e, em seguida, excluí-lo depois que ele não for mais necessário. Um usuário mal-intencionado que obtenha acesso ao arquivo .publishsettings pode editar, criar e excluir o aplicativo de funções.

  2. Novamente, na guia Publicar, selecione as reticências (...) na seção Hosting e escolha Anexar depurador.

    Screenshot of attaching the debugger from Visual Studio.

    O Visual Studio se conecta ao aplicativo de funções e habilita a depuração remota, caso ainda não esteja habilitada.

    Observação

    Como o depurador remoto não é capaz de se conectar ao processo de host, você pode ver um erro. De qualquer forma, a depuração padrão não será dividida em seu código.

  3. De volta ao Visual Studio, copie a URL do Site em Hosting na página Publicar.

  4. No menu Depurar, selecione Anexar ao Processo e, na janela Anexar ao processo, cole a URL no Destino de Conexão, remova https:// e acrescente a porta :4024.

    Verifique se o destino tem aparência <FUNCTION_APP>.azurewebsites.net:4024 e pressione Enter.

    Visual Studio attach to process dialog

  5. Se solicitado, permita o acesso do Visual Studio por meio do firewall local.

  6. Quando solicitado a inserir credenciais, em vez de credenciais de usuário local, escolha uma conta diferente (Mais opções no Windows). Forneça os valores de userName e userPWD no perfil de publicação de Endereço de email e Senha na caixa de diálogo de autenticação no Windows. Depois que uma conexão segura é estabelecida com o servidor de implantação, os processos disponíveis são mostrados.

    Visual Studio enter credential

  7. Marque Mostrar processos de todos os usuários, escolha dotnet.exe e selecione Anexar. Quando a operação for concluída, você será anexado ao código da biblioteca de classes C# em execução em um processo de trabalho isolado. Neste ponto, você pode depurar seu aplicativo de funções normalmente.

Desabilitar depuração remota

Depois de concluir a depuração remota do código, você deve desabilitar a depuração remota no portal do Azure. A depuração remota é desabilitada automaticamente após 48 horas, caso você esqueça.

  1. Na guia Publicar em seu projeto, selecione as reticências (...) na seção Hosting e escolha Abrir no portal do Azure. Essa ação abre o aplicativo de funções no portal do Azure no qual seu projeto é implantado.

  2. No aplicativo de funções, selecione Configuração em configurações, escolha Configurações Gerais, defina Depuração Remota como Desativado e selecione Salvar e Continuar.

Depois que o aplicativo de funções for reiniciado, você não poderá mais se conectar remotamente aos seus processos remotos. Você pode usar essa mesma guia no portal do Azure para habilitar a depuração remota fora do Visual Studio.

Funções de monitoramento

A maneira recomendada de monitorar a execução de suas funções é a integração do aplicativo de funções com o Azure Application Insights. Ao criar um aplicativo de funções no portal do Azure, essa integração é realizada por padrão. No entanto, ao criar o aplicativo de funções durante a publicação do Visual Studio, a integração no aplicativo de funções no Azure não é realizada. Para saber como conectar o Application Insights ao seu aplicativo de funções, confira Habilitar a integração do Application Insights.

Para saber mais sobre o monitoramento usando o Application Insights, confira Monitorar o Azure Functions.

Funções de teste

Esta seção descreve como criar um projeto de aplicativo de funções C# no Visual Studio e executar testes com o xUnit.

Testing Azure Functions with C# in Visual Studio

Instalação

Para configurar seu ambiente, crie uma função e teste o aplicativo. As etapas a seguir ajudam você a criar os aplicativos e as funções necessários para os testes:

  1. Crie um aplicativo de funções e nomeie-o como Functions
  2. Crie uma função HTTP a partir do modelo e nomeie-a MyHttpTrigger.
  3. Crie uma função temporizadora do modelo e nomeie-a MyTimerTrigger.
  4. Crie um aplicativo de teste xUnit na solução e nomeie-o como functions. Tests. Remova os arquivos de teste padrão.
  5. Use NuGet para adicionar uma referência do aplicativo para teste para Microsoft.AspNetCore.Mvc
  6. Referencie o aplicativo Functions no aplicativo Functions.Test.

Criar classes de teste

Agora que os projetos foram criados, será possível criar as classes usadas para executar os testes automatizados.

Cada função usa uma instância do ILogger para manipular o log de mensagens. Alguns testes não registram mensagens ou não se preocupam com como log é implementado. Outros testes precisam avaliar as mensagens registradas para determinar se foram aprovadas.

Você criará uma classe chamada ListLogger, que contém uma lista interna de mensagens a serem avaliadas durante os testes. Para implementar a interface ILogger necessária, a classe precisa de um escopo. A classe a seguir simula um escopo para os casos de teste passar para a classe ListLogger.

Crie uma nova classe no projeto functions.Tests nomeada NullScope.cs e insira o código a seguir:

using System;

namespace Functions.Tests
{
    public class NullScope : IDisposable
    {
        public static NullScope Instance { get; } = new NullScope();

        private NullScope() { }

        public void Dispose() { }
    }
}

Em seguida, crie uma nova classe no projeto functions.Tests nomeada ListLogger.cs e insira o código a seguir:

using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace Functions.Tests
{
    public class ListLogger : ILogger
    {
        public IList<string> Logs;

        public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;

        public bool IsEnabled(LogLevel logLevel) => false;

        public ListLogger()
        {
            this.Logs = new List<string>();
        }

        public void Log<TState>(LogLevel logLevel,
                                EventId eventId,
                                TState state,
                                Exception exception,
                                Func<TState, Exception, string> formatter)
        {
            string message = formatter(state, exception);
            this.Logs.Add(message);
        }
    }
}

A classe ListLogger implementará os seguintes membros, conforme contratado pela interface ILogger:

  • BeginScope: define o escopo de adicionar contexto do log. Nesse caso, o teste somente aponta para a instância estática na classe NullScope para permitir que o teste funcione.

  • IsEnabled: um valor padrão de false é fornecido.

  • Log: esse método usa a função formatter fornecida para formatar a mensagem e, em seguida, adiciona o texto resultante à coleção Logs.

A coleção Logs é uma instância de List<string> e é inicializada no construtor.

Em seguida, crie um novo arquivo no projeto functions.Tests nomeado LoggerTypes.cs e insira o código a seguir:

namespace Functions.Tests
{
    public enum LoggerTypes
    {
        Null,
        List
    }
}

Esta enumeração especifica o tipo de agente usado pelos testes.

Agora, crie uma nova classe no projeto functions.Tests nomeada TestFactory.cs e insira o código a seguir:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Primitives;
using System.Collections.Generic;

namespace Functions.Tests
{
    public class TestFactory
    {
        public static IEnumerable<object[]> Data()
        {
            return new List<object[]>
            {
                new object[] { "name", "Bill" },
                new object[] { "name", "Paul" },
                new object[] { "name", "Steve" }

            };
        }

        private static Dictionary<string, StringValues> CreateDictionary(string key, string value)
        {
            var qs = new Dictionary<string, StringValues>
            {
                { key, value }
            };
            return qs;
        }

        public static HttpRequest CreateHttpRequest(string queryStringKey, string queryStringValue)
        {
            var context = new DefaultHttpContext();
            var request = context.Request;
            request.Query = new QueryCollection(CreateDictionary(queryStringKey, queryStringValue));
            return request;
        }

        public static ILogger CreateLogger(LoggerTypes type = LoggerTypes.Null)
        {
            ILogger logger;

            if (type == LoggerTypes.List)
            {
                logger = new ListLogger();
            }
            else
            {
                logger = NullLoggerFactory.Instance.CreateLogger("Null Logger");
            }

            return logger;
        }
    }
}

A classe TestFactory implementa os seguintes membros:

  • Data: essa propriedade retorna uma coleção IEnumerable de dados de exemplo. Os pares chave-valor representam valores que são passados para uma cadeia de caracteres de consulta.

  • CreateDictionary: esse método aceita um par chave-valor como argumentos e retorna um novo Dictionary usado para criar QueryCollection para representar valores de cadeia de caracteres de consulta.

  • CreateHttpRequest: esse método cria uma solicitação HTTP inicializada com os parâmetros de cadeia de caracteres de consulta fornecidos.

  • CreateHttpRequest: com base no tipo de agente, esse método retornará uma classe de agente usada para teste. O ListLogger controla as mensagens registradas disponíveis para avaliação em testes.

Por fim, crie uma nova classe no projeto Functions.Tests nomeada FunctionsTests.cs e insira o código a seguir:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Xunit;

namespace Functions.Tests
{
    public class FunctionsTests
    {
        private readonly ILogger logger = TestFactory.CreateLogger();

        [Fact]
        public async void Http_trigger_should_return_known_string()
        {
            var request = TestFactory.CreateHttpRequest("name", "Bill");
            var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
            Assert.Equal("Hello, Bill. This HTTP triggered function executed successfully.", response.Value);
        }

        [Theory]
        [MemberData(nameof(TestFactory.Data), MemberType = typeof(TestFactory))]
        public async void Http_trigger_should_return_known_string_from_member_data(string queryStringKey, string queryStringValue)
        {
            var request = TestFactory.CreateHttpRequest(queryStringKey, queryStringValue);
            var response = (OkObjectResult)await MyHttpTrigger.Run(request, logger);
            Assert.Equal($"Hello, {queryStringValue}. This HTTP triggered function executed successfully.", response.Value);
        }

        [Fact]
        public void Timer_should_log_message()
        {
            var logger = (ListLogger)TestFactory.CreateLogger(LoggerTypes.List);
            new MyTimerTrigger().Run(null, logger);
            var msg = logger.Logs[0];
            Assert.Contains("C# Timer trigger function executed at", msg);
        }
    }
}

Os membros implementados nesta classe são:

  • Http_trigger_should_return_known_string: esse teste cria uma solicitação com os valores da cadeia de caracteres de consulta de name=Bill para uma função HTTP e verifica se a resposta esperada será retornada.

  • Http_trigger_should_return_string_from_member_data: esse teste usa atributos xUnit para fornecer dados de exemplo para a função HTTP.

  • Timer_should_log_message: esse teste cria uma instância de ListLogger e a envia a uma função de temporizador. Depois que a função é executada, o log é verificado para garantir que a mensagem esperada esteja presente.

Se você quiser acessar as configurações do aplicativo em seus testes, poderá injetar uma instância IConfiguration com valores de variável de ambiente fictícios na função.

Executar testes

Para executar os testes, navegue até o Gerenciador de Testes e selecione Executar Todos os Testes na Exibição.

Testing Azure Functions with C# in Visual Studio

Depurar testes

Para depurar os testes, defina um ponto de interrupção em um teste, navegue até o Gerenciador de Testes e clique em Executar > Depurar Última Execução.

Ferramentas do Azure Functions com o Visual Studio 2017

As Ferramentas do Azure Functions estão disponíveis na carga de trabalho de desenvolvimento do Azure, começando com o Visual Studio 2017. No Visual Studio 2017, a carga de trabalho de desenvolvimento do Azure instala as Ferramentas do Azure Functions como uma extensão separada. No Visual Studio 2019 e posterior, a extensão das ferramentas do Azure Functions é atualizada como parte do Visual Studio.

Ao atualizar a instalação do Visual Studio 2017, verifique se você está usando a versão mais recente das Ferramentas do Azure Functions. As seções a seguir mostram como verificar e (se necessário) atualizar sua extensão das Ferramentas do Azure Functions no Visual Studio 2017.

Verifique a versão das ferramentas no Visual Studio 2017

  1. No menu Ferramentas, clique em Extensões e Atualizações. Expanda Instalado>Ferramentas e escolha Azure Functions e Ferramentas de Trabalhos da Web.

    Verify the Functions tools version

  2. Observe a Versão instalada e compare-a com a versão mais recente listada nas notas sobre a versão.

  3. Se a sua versão for mais antiga, atualize suas ferramentas no Visual Studio conforme mostrado na seção a seguir.

Atualizar suas ferramentas no Visual Studio

  1. Na caixa de diálogo Extensões e Atualizações, expanda Atualizações>Visual Studio Marketplace, escolha Azure Functions e Ferramentas de Trabalhos da Web e selecione Atualizar.

    Update the Functions tools version

  2. Depois de fazer o download da atualização das ferramentas, selecione Fechar e feche o Visual Studio para disparar a atualização das ferramentas usando o instalador VSIX.

  3. No instalador VSIX, escolha Modificar para atualizar as ferramentas.

  4. Depois que a atualização for concluída, escolha Fechar e reinicie o Visual Studio.

Próximas etapas

Para obter mais informações sobre o Azure Functions Core Tools, confira Trabalhar com o Azure Functions Core Tools.

Para obter mais informações sobre como desenvolver funções como bibliotecas de classes do .NET, confira Referência do desenvolvedor de C# do Azure Functions. Este artigo também contém links de exemplos de como usar atributos para declarar os vários tipos de associações compatíveis com o Azure Functions.