Configuration Util
La clase ConfigurationUtil proporciona métodos utilitarios para facilitar la creación de instancias de IConfiguration en pruebas unitarias usando xUnit. Su propósito principal es permitir la configuración de aplicaciones basada en objetos de configuración simples, simulando el uso de archivos appsettings.json.
namespace CodeDesignPlus.Net.xUnit.Extensions;
/// <summary>/// Provides utility methods for configuration management in xUnit tests./// </summary>public static class ConfigurationUtil{ /// <summary> /// Creates an <see cref="IConfiguration"/> instance from the provided app settings object. /// </summary> /// <param name="appSettings">The application settings object to be serialized to JSON. Default is null.</param> /// <returns>An <see cref="IConfiguration"/> instance containing the serialized app settings.</returns> public static IConfiguration GetConfiguration(object appSettings = null) { // Serialize the app settings object to JSON. var json = JsonSerializer.Serialize(appSettings);
// Convert the JSON string to a memory stream. var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json));
// Build and return the configuration from the JSON stream. return new ConfigurationBuilder().AddJsonStream(memoryStream).Build(); }}Dependencias y Requisitos Previos
Section titled “Dependencias y Requisitos Previos”Microsoft.Extensions.Configuration: Necesario para la interfazIConfigurationy la construcción de la configuración.System.Text.Json: Necesario para serializar objetos a JSON.System.IO: Necesario para el uso deMemoryStream.System.Text: Necesario para la codificación UTF8.
Escenarios de uso
Section titled “Escenarios de uso”Esta clase es particularmente útil en pruebas unitarias (xUnit) donde se necesita:
- Simular la configuración de una aplicación sin la necesidad de archivos
appsettings.json. - Probar el comportamiento de componentes que dependen de la configuración de la aplicación.
- Configurar diferentes escenarios de prueba con diferentes configuraciones de forma rápida y controlada.
Beneficios
Section titled “Beneficios”- Flexibilidad: Permite definir la configuración de forma programática usando objetos C#.
- Facilidad de uso: Simplifica la creación de instancias
IConfigurationpara pruebas, evitando la necesidad de cargar archivos de configuración desde el disco. - Aislamiento: Permite que las pruebas sean independientes de la configuración real de la aplicación, lo cual es crucial para pruebas unitarias.
Ejemplo Práctico
Section titled “Ejemplo Práctico”Este ejemplo muestra cómo usar ConfigurationUtil para configurar la inyección de dependencias:
using Xunit;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Configuration;using CodeDesignPlus.Net.xUnit.Helpers;
public class ExampleServiceTests{ [Fact] public void MyService_Should_BeConfiguredCorrectly() { // Arrange: Define un objeto de configuración simple var configSettings = new { MyService = new { ApiKey = "test-key", Timeout = 10 } };
// Usamos ConfigurationUtil para crear un IConfiguration var configuration = ConfigurationUtil.GetConfiguration(configSettings);
// Aquí puedes verificar que la configuración es correcta Assert.Equal("test-key", configuration["MyService:ApiKey"]); Assert.Equal("10", configuration["MyService:Timeout"]);
// Luego, puedes usar esta configuración para configurar tus servicios var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton<MyService>(sp => new MyService(configuration));
var serviceProvider = serviceCollection.BuildServiceProvider();
// Act: Obtén la instancia de MyService var myService = serviceProvider.GetRequiredService<MyService>();
// Assert: Verifica que la configuración se haya aplicado correctamente Assert.Equal("test-key", myService.ApiKey); Assert.Equal(10, myService.Timeout); }}public class MyService{ public string ApiKey {get;} public int Timeout {get;}
public MyService(IConfiguration configuration) { ApiKey = configuration["MyService:ApiKey"]; Timeout = int.Parse(configuration["MyService:Timeout"]); }}En este ejemplo:
- Definimos una clase de configuración llamada
MyServiceque obtiene sus propiedades de la configuración. - Creamos un objeto de configuración anonimo llamado
configSettings - Usamos
ConfigurationUtil.GetConfigurationpara crear unIConfigurationa partir del objeto anónimoconfigSettings. - Se agrega
MyServicecomo singleton utilizando la configuración creada. - Verificamos que la configuración en el objeto
MyServicees la que se esperaba
Métodos de extensión
Section titled “Métodos de extensión”La clase ConfigurationUtil proporciona un método estático para crear instancias de IConfiguration a partir de objetos de configuración simples. A continuación se detallan los métodos disponibles:
GetConfiguration
Section titled “GetConfiguration”El método GetConfiguration permite crear una instancia de IConfiguration a partir de un objeto de configuración. Este método es estático y no requiere instanciar la clase ConfigurationUtil.
public static IConfiguration GetConfiguration(object appSettings = null)-
Parámetros:
appSettings: Un objeto que representa la configuración de la aplicación. Este objeto será serializado a JSON y utilizado para construir la configuración. El valor por defecto esnull.
-
Tipo de retorno:
IConfiguration: Una instancia deIConfigurationque contiene la configuración serializada del objetoappSettings.
-
Ejemplos de código:
Los siguientes ejemplos muestran cómo usar el método
GetConfigurationcon diferentes tipos de objetos de configuración.Este ejemplo muestra cómo usar
GetConfigurationsin un objeto de configuración. En este caso, se crea una instancia deIConfigurationvacía.var config = ConfigurationUtil.GetConfiguration();Assert.NotNull(config); // Verifica que no es nuloEste ejemplo muestra cómo usar
GetConfigurationcon un objeto de configuración simple:var config = ConfigurationUtil.GetConfiguration(new { MyKey = "my valueAssert.Equal("my value", config["MyKey"]);Este ejemplo muestra cómo usar
GetConfigurationcon un objeto de configuración anidado:var config = ConfigurationUtil.GetConfiguration(new {Logging = new {LogLevel = new {Default = "Information"}}});Assert.Equal("Information", config["Logging:LogLevel:Default"]);
Conclusiones
Section titled “Conclusiones”- La clase
ConfigurationUtilproporciona una forma sencilla y eficiente de crear instancias deIConfigurationen pruebas unitarias. - Permite una configuración basada en objetos, evitando la necesidad de archivos de configuración.
- Facilita la escritura de pruebas más limpias y controladas.
- Es esencial usar esta herramienta en pruebas que dependan de
IConfiguration, ya que te permitirá mantener la prueba aislada de la configuración de la aplicación. - Es importante considerar las posibles excepciones al serializar objetos complejos.