Desarrollo de Azure Functions con Visual Studio
Visual Studio le permite desarrollar, probar e implementar funciones de la biblioteca de clases C# en Azure. Si esta es la primera experiencia con Azure Functions, vea Introducción a Azure Functions.
Visual Studio proporciona las ventajas siguientes al desarrollar funciones:
- Editar, compilar y ejecutar funciones en el equipo de desarrollo local.
- Publique su proyecto de Azure Functions directamente en Azure y cree recursos de Azure según sea necesario.
- Use atributos de C# para declarar enlaces de función directamente en el código de C#.
- Desarrollar e implementar funciones de C# compiladas previamente. Las funciones compiladas previamente proporcionan un mejor rendimiento de arranque en frío que las funciones basadas en scripts de C#.
- Programar las funciones en C# a la vez que se tienen todos los beneficios del desarrollo de Visual Studio.
En este artículo se dan detalles sobre cómo usar Visual Studio para desarrollar funciones de biblioteca de clases C# y publicarlas en Azure. Antes de leer este artículo, le recomendamos que complete la guía de inicio rápido de Functions para Visual Studio.
A menos que se indique lo contrario, los procedimientos y los ejemplos que se muestran son para Visual Studio 2022. Para obtener más información sobre las versiones de Visual Studio 2022, consulte las notas de la versión o las notas de la versión preliminar.
Requisitos previos
Herramientas de Azure Functions. Para agregar las herramientas de Azure Functions, asegúrese de incluir la carga de trabajo Desarrollo de Azure en la instalación de Visual Studio. Si usa Visual Studio 2017, es posible que tenga que realizar algunos pasos adicionales en la instalación.
Los demás recursos que necesita, como una cuenta de Azure Storage, se crean en la suscripción durante el proceso de publicación.
-
Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar.
Creación de un proyecto de Azure Functions
La plantilla del proyecto de Azure Functions de Visual Studio crea un proyecto de biblioteca de clases de C# que puede publicar en una aplicación de funciones en Azure. Una aplicación de funciones permite agrupar funciones como una unidad lógica para facilitar la administración, la implementación, el escalado y el uso compartido de recursos.
En el menú de Visual Studio, seleccione Archivo>Nuevo>Proyecto.
En Crear un proyecto, escriba functions en el cuadro de búsqueda, elija la plantilla Azure Functions y seleccione Siguiente.
En Configurar el nuevo proyecto, escriba un nombre de proyecto para el proyecto y, a continuación, seleccione Crear. El nombre de la aplicación de función debe ser válido como espacio de nombres de C#, por lo que no debe usar guiones bajos, guiones u otros caracteres no alfanuméricos.
En la configuración de Crear aplicación de Azure Functions, use los valores de la tabla siguiente:
Configuración valor Descripción Versión de .NET .NET 6 aislado Este valor crea un proyecto de función que se ejecuta en un proceso de trabajo aislado. Para más información, consulte Selección de un destino para versiones de runtime de Azure Functions. Plantilla de función desencadenador HTTP Este valor crea una función desencadenada por una solicitud HTTP. Cuenta de almacenamiento (AzureWebJobsStorage) Emulador de Storage Dado que una aplicación de funciones de Azure necesita una cuenta de almacenamiento, se asigna o se crea una cuando publica su proyecto en Azure. Un desencadenador HTTP no utiliza una cadena de conexión de cuenta de Azure Storage; todos los demás tipos de desencadenador requieren una cadena de conexión de cuenta de Azure Storage válida. Nivel de autorización Anónimo Cualquier cliente puede desencadenar una función creada sin tener que proporcionar una clave. Esta configuración de autorización facilita probar la función nueva. Para más información sobre las claves y la autorización, consulte Claves de autorización e Introducción a los enlaces y desencadenadores HTTP de Azure Functions. Asegúrese de establecer el Nivel de autorización en Anónimo. Al elegir el nivel predeterminado de Función, tiene que presentar la tecla de función en las solicitudes para acceder al punto de conexión de la función.
Seleccione Crear para crear el proyecto de función y la función con desencadenador HTTP.
Después de crear un proyecto de Azure Functions, la plantilla de proyecto crea un proyecto de C#, instala el paquete NuGet Microsoft.NET.Sdk.Functions
y establece la plataforma de destino. El proyecto nuevo contiene los archivos siguientes:
host.json: permite configurar el host de Functions. Esta configuración se aplica tanto cuando se ejecuta localmente como en Azure. Para más información, consulte la referencia sobre host.json.
local.settings.json: mantiene la configuración que se usa cuando se ejecutan localmente las funciones. Esta configuración no se usa cuando se ejecuta en Azure. Para más información, consulte Archivo de configuración local.
Importante
Como el archivo local.settings.json puede contener secretos, debe excluirlo del control de código fuente del proyecto. Asegúrese de que el valor Copiar en el directorio de salida para este archivo esté establecido en Copiar si es posterior.
Para más información, consulte Proyecto de biblioteca de clases de Functions.
Trabajar con la configuración de la aplicación localmente
Cuando se ejecuta en una aplicación de funciones de Azure, la configuración requerida por las funciones se almacena de forma segura en la configuración de la aplicación. Durante el desarrollo local, esta configuración se agrega en su lugar a la colección Values
del archivo local.settings.json. El archivo local.settings.json almacena también la configuración que usan las herramientas locales de desarrollo.
Los elementos de la colección Values
del archivo local.settings.json del proyecto están diseñados para reflejar elementos en la configuración de la aplicación de la aplicación de funciones en Azure.
Visual Studio no carga de forma automática la configuración de local.settings.json al publicar el proyecto. Para asegurarse de que esta configuración también existe en la aplicación de funciones de Azure, debe cargarla después de publicar el proyecto. Para obtener más información, vea Configuración de aplicación de funciones. Los valores de una colección ConnectionStrings
nunca se publican.
El código también puede leer los valores de configuración de la aplicación de funciones como variables de entorno. Para más información, consulte Variables de entorno.
Configuración del proyecto para el desarrollo local
El entorno de tiempo de ejecución de Functions usa internamente una cuenta de Azure Storage. Para todos los tipos de desencadenadores distintos de HTTP y webhooks, establezca la clave Values.AzureWebJobsStorage
en una cadena de conexión de cuenta de Azure Storage válida. La aplicación de funciones también puede usar el emulador de Azurite para la configuración de conexión AzureWebJobsStorage
que necesita el proyecto. Para usar el emulador, establezca el valor de AzureWebJobsStorage
en UseDevelopmentStorage=true
. Cambie esta configuración a una cadena de conexión de la cuenta de almacenamiento real antes de la implementación. Para más información, consulte Emulador de almacenamiento local.
Para establecer la cadena de conexión de cuenta de almacenamiento:
En Azure Portal, vaya a la cuenta de almacenamiento.
En la pestaña Claves de acceso, debajo de Seguridad y redes, copie la cadena de conexión de key1.
En el proyecto, abra el archivo local.settings.json y establezca el valor de la clave
AzureWebJobsStorage
en la cadena de conexión que ha copiado.Repita el paso anterior para agregar claves únicas a la matriz
Values
de cualquier otra conexión necesaria para las funciones.
Incorporación de una función al proyecto
En las funciones de biblioteca de clases C#, los enlaces que la función usa se definen mediante la aplicación de atributos en el código. Al crear los desencadenadores de funciones a partir de las plantillas proporcionadas, los atributos del desencadenador se aplican automáticamente.
En el Explorador de soluciones, haga clic con el botón derecho en el nodo del proyecto y seleccione Agregar>Nuevo elemento.
Seleccione Función de Azure, escriba un nombre para la clase y, luego, seleccione Agregar.
Elija el desencadenador, establezca las propiedades de enlace y, después, seleccione Agregar. En el ejemplo siguiente se muestra los valores para crear una función de desencadenador de Queue Storage.
A continuación, se le solicitará que elija entre el emulador de almacenamiento de Azure o hacer referencia a una cuenta de almacenamiento de Azure aprovisionada.
En este ejemplo de desencadenador se usa una cadena de conexión con una clave denominada
QueueStorage
. Esta clave, que está almacenada en el archivo local.settings.json, hace referencia al emulador de Azurite o a una cuenta de almacenamiento de Azure.Examine la clase recién agregada. Verá un método
Run()
con el atributoFunctionName
. Este atributo indica que el método es el punto de entrada de la función.Por ejemplo, la clase de C# siguiente representa una función de desencadenador de Queue Storage básica:
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}"); } } }
Se aplica un atributo específico de enlace a cada parámetro de enlace que se suministra al método de punto de entrada. El atributo toma la información de enlace como parámetros. En el ejemplo anterior, el primer parámetro tiene aplicado un atributo QueueTrigger
, que indica una función de desencadenador de Queue Storage. El nombre de la cola y el valor de la cadena de conexión se pasan como parámetros en el atributo QueueTrigger
. Para más información, consulte Enlaces de Azure Queue Storage para Azure Functions.
Use el procedimiento anterior para agregar más funciones al proyecto de aplicación de funciones. Cada función del proyecto puede tener un desencadenador diferente, pero una función no puede tener más de un desencadenador. Para más información, consulte Conceptos básicos sobre los enlaces y desencadenadores de Azure Functions.
Adición de enlaces
Al igual que sucede con los desencadenadores, los enlaces de entrada y salida se agregan a la función como atributos de enlace. Agregue los enlaces a una función como se indica a continuación:
Asegúrese de que ha configurado el proyecto para desarrollo local.
Agregue el paquete de extensión NuGet adecuado para el enlace específico mediante la búsqueda de los requisitos de paquete de NuGet específicos del enlace en el artículo de referencia para el enlace. Por ejemplo, buscar los requisitos del paquete para el desencadenador de Event Hubs en el artículo de referencia Enlaces de Azure Event Hubs.
Use el siguiente comando en la consola de Administrador de paquetes para instalar un paquete específico:
Install-Package Microsoft.Azure.Functions.Worker.Extensions.<BINDING_TYPE> -Version <TARGET_VERSION>
En este ejemplo, reemplace
<BINDING_TYPE>
por el nombre específico de la extensión de enlace y<TARGET_VERSION>
por una versión específica del paquete, como3.0.0-beta5
. Las versiones válidas se enumeran en las páginas individuales del paquete en NuGet.org. Las versiones principales que corresponden al tiempo de ejecución de Functions 1.x o 2.x se especifican en el artículo de referencia del enlace.Si hay valores de la aplicación que el enlace necesita, agréguelos a la colección
Values
del archivo de configuración local.La función usa estos valores cuando se ejecuta localmente. Cuando la función se ejecuta en la aplicación de funciones en Azure, usa los valores de la aplicación de funciones.
Agregue el atributo de enlace apropiado para la firma del método. En el ejemplo siguiente, un mensaje de la cola desencadena la función y el enlace de salida, se crea un nuevo mensaje de la cola con el mismo texto en otra cola.
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; } }
La conexión con el almacenamiento en la cola se obtiene del valor
AzureWebJobsStorage
. Para más información, consulte el artículo de referencia del enlace concreto.
Para obtener una lista completa de los enlaces admitidos por Functions, consulte Enlaces admitidos.
Ejecución local de funciones
Azure Functions Core Tools le permite ejecutar un proyecto de Azure Functions en el equipo de desarrollo local. Al presionar F5 para depurar un proyecto de Functions, el host de Functions local (func.exe) comienza a escuchar en un puerto local (normalmente 7071). Los puntos de conexión de función a los que se puede llamar se escriben en la salida y puede usarlos para probar las funciones. Para más información, consulte Uso de Azure Functions Core Tools. La primera vez que inicie una función desde Visual Studio Code se le solicitará que instale estas herramientas.
Para iniciar la función en Visual Studio en modo de depuración, haga lo siguiente:
Presione F5. Si se le solicita, acepte la solicitud de Visual Studio para descargar e instalar las herramientas de Azure Functions Core (CLI). También es preciso que habilite una excepción de firewall para que las herramientas para controlen las solicitudes de HTTP.
Con el proyecto en ejecución, pruebe el código como probaría una función implementada.
Cuando Visual Studio se ejecuta en modo de depuración, los puntos de interrupción se alcanzan de la forma esperada.
Para obtener un escenario de prueba más detallado mediante Visual Studio, consulte Funciones de prueba.
Publicación en Azure
Al publicar desde Visual Studio, se usa uno de los dos métodos de implementación:
- Web Deploy: empaqueta e implementa aplicaciones Windows en cualquier servidor IIS.
- Implementación desde archivo ZIP con la ejecución desde un archivo de paquete habilitada: se recomienda para las implementaciones de Azure Functions.
Siga estos pasos para publicar el proyecto en una aplicación de funciones de Azure.
En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Publicar. En Destino, seleccione Azure y, luego, Siguiente.
Seleccione la opción Aplicación de funciones de Azure (Windows) en la pestaña Destino específico. Esta opción creará una aplicación de funciones que se ejecutará en Windows. Después, seleccione el botón Siguiente.
En Instancia de la función, seleccione Crear una aplicación de Azure Functions...
Crear una nueva instancia con los valores especificados en la tabla siguiente:
Configuración valor Descripción Nombre Nombre único globalmente Nombre que identifica de forma única la nueva aplicación de función. Acepte este nombre o escriba uno nuevo. Los caracteres válidos son a-z
,0-9
y-
.Suscripción Su suscripción La suscripción de Azure que se va a usar. Acepte esta suscripción o seleccione una nueva en la lista desplegable. Grupo de recursos Nombre del grupo de recursos Nombre del grupo de recursos en el que quiere crear la aplicación de funciones. Seleccione un grupo de recursos existente en la lista desplegable o la opción Nuevo para crear un nuevo grupo de recursos. Tipo de plan Consumo Cuando publique el proyecto en una aplicación de funciones que se ejecute en un plan Consumo, solo pagará por las ejecuciones de la aplicación. Otros planes de hospedaje suponen costos más elevados. Ubicación Ubicación de la instancia de App Service Elija una ubicación en una región próxima a usted o a otros servicios a los que las funciones accedan. Azure Storage Cuenta de almacenamiento de uso general El runtime de Functions necesita una cuenta de almacenamiento de Azure. Seleccione Nueva para configurar una cuenta de almacenamiento de uso general. También puede elegir una cuenta existente que cumpla los requisitos de la cuenta de almacenamiento. Seleccione Crear para crear una aplicación de funciones y sus recursos relacionados en Azure. El estado de la creación del recurso se muestra en la parte inferior izquierda de la ventana.
En la instancia de Functions, asegúrese de que Ejecutar desde el archivo de paquete esté activado. La aplicación de funciones se implementa con la implementación de un archivo zip y con el modo de ejecución desde el paquete habilitado. La implementación de archivo ZIP es el método de implementación recomendado para el proyecto de Functions, ya que se obtiene un mejor rendimiento.
Seleccione Finalizary, en la página Publicar, seleccione Publicar para implementar el paquete que contiene los archivos de proyecto en la nueva aplicación de funciones en Azure.
Una vez finalizada la implementación, en la pestaña Publicar aparecerá la dirección URL raíz de la aplicación de funciones de Azure.
En la pestaña Publicar, en la sección Hospedaje, elija Abrir en Azure Portal. Esto abre el recurso de Azure de aplicación de funciones nuevo en Azure Portal.
Configuración de Function App
Visual Studio no carga automáticamente esta configuración cuando publica el proyecto. Todos los valores que agregue a local.settings.json también se deben agregar a la aplicación de funciones en Azure.
La manera más sencilla de cargar la configuración necesaria en la aplicación de funciones en Azure consiste en expandir los tres puntos situados junto a la sección Hospedaje y seleccionar el vínculo Administrar la configuración de Azure App Service que aparece después de publicar correctamente el proyecto.
Al seleccionar este vínculo se muestra el cuadro de diálogo Configuración de la aplicación para la aplicación de funciones, donde puede agregar una configuración de la aplicación nueva o modificar las existentes.
Local muestra un valor de configuración en el archivo local.settings.json y Remoto un valor actual de la aplicación de funciones de Azure. Elija Agregar configuración para crear una nueva configuración de aplicación. Use el vínculo Insertar un valor desde Local para copiar un valor de configuración para el campo Remoto. Los cambios pendientes se escriben en el archivo de configuración local y la aplicación de función cuando se selecciona Aceptar.
Nota
De forma predeterminada, el archivo local.settings.json no se ha insertado en el control de código fuente. Esto significa que si clona un proyecto de Functions local desde el control de código fuente, el proyecto no tiene el archivo local.settings.json. En este caso, debe crear manualmente el archivo local.settings.json en la raíz del proyecto para que el cuadro de diálogo Configuración de la aplicación funcione según lo previsto.
También puede administrar la configuración de la aplicación en una de estas otras maneras:
- Use Azure Portal.
- Use la opción de publicación
--publish-local-settings
en Azure Functions Core Tools. - Uso de la CLI de Azure.
Depuración remota
Para depurar la aplicación de funciones de forma remota, es preciso publicar una configuración de depuración del proyecto. También debe habilitar la depuración remota en la aplicación de funciones en Azure.
En esta sección se supone que ya ha publicado en la aplicación de funciones mediante una configuración de versión.
Consideraciones sobre la depuración remota
- No se recomienda la depuración remota en servicios de producción.
- Si la depuración de Solo mi código está habilitada, deshabilítela.
- Evite detenciones prolongadas en los puntos de interrupción durante la depuración remota. Azure considera un proceso detenido durante más de unos minutos como un proceso sin respuesta y lo apaga.
- Mientras realiza la depuración, el servidor envía datos a Visual Studio, lo que podría afectar a los cargos de ancho de banda. Para obtener información acerca de las tarifas de ancho de banda, consulte Precios de Azure.
- La depuración remota se deshabilita automáticamente en la aplicación de funciones después de las 48 horas. A las 48 horas, habrá que volver a habilitarla.
Asociar el depurador
La forma en que se conecta el depurador depende del modo de ejecución. Si se depura una aplicación de proceso de trabajo aislado, actualmente es preciso asociar el depurador remoto a un proceso de .NET independiente y se requieren otros pasos de configuración.
Al terminar, es preciso deshabilitar la depuración remota.
Para conectar un depurador remoto a una aplicación de funciones que se ejecuta en un proceso independiente del host de Functions:
En la pestaña Publicar, seleccione los puntos suspensivos (...) en la sección Hosting y, después, elija Descargar perfil de publicación. Esta acción descarga una copia del perfil de publicación y abre la ubicación de descarga. Necesita este archivo, que contiene las credenciales usadas para conectarse al proceso de trabajo aislado que se ejecuta en Azure.
Precaución
El archivo .publishsettings contiene las credenciales (sin codificar) que se usan para administrar una aplicación de funciones. El procedimiento recomendado para este archivo consiste en almacenarlo temporalmente fuera de los directorios de origen (por ejemplo en la carpeta Bibliotecas\Documentos) y, después, eliminarlo cuando deje de ser necesario. Un usuario malintencionado que obtuviera acceso al archivo .publishsettings podría modificar, crear y eliminar su aplicación de funciones.
Una vez más, en la pestaña Publicar, seleccione los puntos suspensivos (...) en la sección Hosting y, después, elija Adjuntar depurador.
Visual Studio se conecta a la aplicación de funciones y habilita la depuración remota, en caso de que aún no está habilitada.
Nota
Dado que el depurador remoto no se puede conectar al proceso de host, podría ver un error. En cualquier caso, la depuración predeterminada no se dividirá en el código.
De nuevo en Visual Studio, copie la dirección URL de Sitio en Hosting en la página Publicar.
En el menú Depurar, seleccione Asociar al proceso y, en la ventana Asociar al proceso, pegue la dirección URL en Destino de la conexión, quite
https://
y anexe el puerto:4024
.Compruebe que el destino se parece a este
<FUNCTION_APP>.azurewebsites.net:4024
y presione Entrar.Si se le solicita, permita que Visual Studio acceda a través de un firewall local.
Cuando se le pidan credenciales, en lugar de las credenciales de usuario local, elija otra cuenta (Más opciones en Windows). Especifique los valores de userName y userPWD del perfil publicado en Dirección de correo electrónico y Contraseña en el cuadro de diálogo de autenticación en Windows. Una vez establecida una conexión segura con el servidor de implementación, se muestran los procesos disponibles.
Active Mostrar proceso de todos los usuarios y, después, elija dotnet.exe y seleccione Adjuntar. Cuando se completa la operación, se adjunta al código de la biblioteca de clases de C# que se ejecuta en un proceso de trabajo aislado. En este momento, puede depurar la aplicación de funciones de forma normal.
Deshabilitar la depuración remota
Cuando haya terminado de depurar el código de forma remota, debe deshabilitar la depuración remota en Azure Portal. La depuración remota se deshabilita automáticamente a las de 48 horas, por si se le olvida hacerlo.
En la pestaña Publicar del proyecto, seleccione los puntos suspensivos (...) en la sección Hosting y elija Abrir en Azure Portal. Esta acción abre la aplicación de funciones en la instancia de Azure Portal en que se implementa el proyecto.
En la aplicación de funciones, seleccione Configuración en Configuración, elija Configuración general, establezca Depuración remota en Desactivado y, después, seleccione Guardar y Continuar.
Una vez que se reinicie la aplicación de funciones, no podrá conectarse de forma remota a los procesos remotos. Puede usar esta misma pestaña en Azure Portal para habilitar la depuración remota fuera de Visual Studio.
Supervisión de funciones
La forma recomendada de supervisar la ejecución de las funciones es mediante la aplicación de función con Azure Application Insights. De forma predeterminada, cuando crea una aplicación de función en Azure Portal, esta integración se realiza automáticamente. Sin embargo, cuando se crea la aplicación de función durante la publicación de Visual Studio, no se lleva a cabo su integración en Azure. Para obtener información sobre cómo conectar Application Insights a la aplicación de funciones, consulte Habilitación de la integración de Application Insights.
Para obtener más información sobre la supervisión mediante Application Insights, consulte Supervisión de Azure Functions.
Funciones de prueba
En esta sección se describe cómo crear un proyecto de aplicación de funciones de C# en Visual Studio y cómo ejecutar y realizar pruebas con xUnit.
Instalación
Para configurar el entorno, cree una función y pruebe la aplicación. Los pasos siguientes le ayudarán a crear las aplicaciones y funciones necesarias para admitir las pruebas:
- Cree una nueva aplicación de Functions y asígnele el nombre Functions.
- Cree una función HTTP a partir de la plantilla y asígnele el nombre MyHttpTrigger.
- Cree una función de temporizador a partir de la plantilla y asígnele el nombre MyTimerTrigger.
- Cree una aplicación de prueba en xUnit en la solución y asígnele el nombre Functions.Test. Quite los archivos de prueba predeterminados.
- Use NuGet para agregar referencias desde la aplicación de prueba a Microsoft.AspNetCore.Mvc
- Haga referencia a la aplicación Functions desde la aplicación Functions.Tests.
Crear clases de prueba
Ahora que se han creado los proyectos, puede crear las clases usadas para ejecutar las pruebas automatizadas.
Cada función toma una instancia de ILogger para controlar el registro de mensajes. Algunas pruebas no registran los mensajes o no tiene que preocuparse por cómo se implementa el registro. Otras pruebas deben evaluar los mensajes registrados para determinar si están pasando una prueba.
Creará una clase denominada ListLogger
que contiene una lista interna de los mensajes que se evaluarán durante las pruebas. Para implementar la interfaz de ILogger
necesaria, la clase necesita un ámbito. La siguiente clase simula un ámbito para los casos de prueba que se van a pasar a la clase ListLogger
.
Cree una nueva clase en el proyecto Functions.Tests denominada NullScope.cs y escriba el código siguiente:
using System;
namespace Functions.Tests
{
public class NullScope : IDisposable
{
public static NullScope Instance { get; } = new NullScope();
private NullScope() { }
public void Dispose() { }
}
}
A continuación, cree una nueva clase en el proyecto Functions.Tests denominada ListLogger.cs y escriba el código siguiente:
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);
}
}
}
La clase ListLogger
implementa los siguientes miembros según los contrata la interfaz ILogger
:
BeginScope: Los ámbitos agregan contexto al registro. En este caso, la prueba simplemente apunta a la instancia estática en la clase
NullScope
para permitir la prueba de la función.IsEnabled: Se proporciona un valor predeterminado de
false
.Log: Este método usa la función
formatter
proporcionada para dar formato al mensaje y, a continuación, agrega el texto resultante a la colecciónLogs
.
La colección Logs
es una instancia de List<string>
y se inicializa en el constructor.
A continuación, cree un archivo nuevo en el proyecto Functions.Tests denominado LoggerTypes.cs y escriba el código siguiente:
namespace Functions.Tests
{
public enum LoggerTypes
{
Null,
List
}
}
Esta enumeración especifica el tipo de registrador utilizado por las pruebas.
A continuación, cree una clase nueva en el proyecto Functions.Tests denominada TestFactory.cs y escriba el código siguiente:
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;
}
}
}
La clase TestFactory
implementa los siguientes miembros:
Data: Esta propiedad devuelve una colección IEnumerable de datos de ejemplo. Los pares clave-valor representan los valores que se pasan en una cadena de consulta.
CreateDictionary: Este método acepta un par clave-valor como argumento y devuelve un
Dictionary
nuevo usado para crearQueryCollection
para representar los valores de cadena de consulta.CreateHttpRequest: Este método crea una solicitud HTTP que se inicializa con los parámetros de cadena de consulta indicados.
CreateLogger: Según el tipo de registrador, este método devuelve una clase de registrador que se usa para las pruebas.
ListLogger
realiza un seguimiento de los mensajes registrados disponibles para su evaluación en las pruebas.
Finalmente, cree una clase nueva en el proyecto Functions.Tests denominada FunctionsTests.cs y escriba el código siguiente:
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);
}
}
}
Los miembros implementados en esta clase son:
Http_trigger_should_return_known_string: Esta prueba crea una solicitud con los valores de la cadena de consulta de
name=Bill
en una función HTTP y comprueba que se devuelve la respuesta esperada.Http_trigger_should_return_string_from_member_data: Esta prueba usa atributos de xUnit para proporcionar datos de ejemplo a la función HTTP.
Timer_should_log_message: esta prueba crea una instancia de
ListLogger
y la pasa a una función de temporizador. Una vez que se ejecuta la función, se comprueba el registro para garantizar que el mensaje esperado está presente.
Si quiere acceder a la configuración de la aplicación en las pruebas, puede insertar una instancia de IConfiguration
con valores de variables de entorno simuladas en la función.
Ejecución de las pruebas
Para ejecutar las pruebas, vaya al Explorador de pruebas y seleccione Ejecutar todas las pruebas en la vista.
Depuración de pruebas
Para depurar las pruebas, establezca un punto de interrupción en una prueba, vaya al Explorador de pruebas y seleccione Ejecutar > Última ejecución de depuración.
Herramientas de Azure Functions con Visual Studio 2017
Las herramientas de Azure Functions están disponibles en la carga de trabajo de desarrollo de Azure a partir de Visual Studio 2017. En Visual Studio 2017, la carga de trabajo de desarrollo de Azure instala las herramientas de Azure Functions como una extensión independiente. En Visual Studio 2019 y versiones posteriores, la extensión de herramientas de Azure Functions se actualiza como parte de Visual Studio.
Al actualizar la instalación de Visual Studio 2017, también debe asegurarse de que usa la versión más reciente de las herramientas de Azure Functions. En las secciones siguientes se muestra cómo comprobar y, si es necesario, actualizar la extensión de herramientas de Azure Functions en Visual Studio 2017.
Comprobar la versión de las herramientas en Visual Studio 2017
En el menú Herramientas, seleccione Extensiones y actualizaciones. Expanda Herramientas>instaladas y, después, elija Azure Functions and Web Jobs Tools.
Observe la Versión instalada y compárela con la versión más reciente que aparece en las notas de la versión.
Si su versión es anterior, actualice las herramientas en Visual Studio como se muestra en la siguiente sección.
Actualización de las herramientas en Visual Studio
En el cuadro de diálogo Extensiones y actualizaciones, expanda Actualizaciones>Visual Studio Marketplace, elija Azure Functions and Web Jobs Tools y seleccione Actualizar.
Después de descargar la actualización de las herramientas, seleccione Cerrar y cierre Visual Studio para desencadenar la actualización de las herramientas con el instalador VSIX.
En el instalador VSIX, elija Modificar para actualizar las herramientas.
Una vez que se haya completado la actualización, elija Cerrar y reinicie Visual Studio.
Pasos siguientes
Para obtener más información sobre Azure Functions Core Tools,vea Uso de Azure Functions Core Tools.
Para obtener más información sobre el desarrollo de funciones como bibliotecas de clases de .NET, vea Referencia para desarrolladores de C# de Azure Functions. Este artículo también tiene vínculos a ejemplos de cómo usar atributos para declarar los distintos tipos de vínculos compatibles con Azure Functions.