returns c# visual-studio unit-testing app-config application-settings

c# - returns - ConfigurationManager.AppSettings devuelve Null en proyecto de prueba de unidad



c# configurationmanager appsettings get returns null (3)

Tengo un proyecto de prueba de unidad C # con la configuración de la aplicación en el archivo app.config . Estoy probando una clase que existe en un proyecto diferente. Esa clase depende de ambos, ConfigurationManager.AppSettings y ConfigurationManager.ConnectionStrings .

El proyecto en el que reside la clase que se está probando no tiene un archivo app.config. Pensé que debido a que la clase está siendo instanciada en el contexto del proyecto de prueba de unidad, usaría el archivo app.config del proyecto de prueba de unidad. De hecho, ese parece ser el caso de la cadena de conexión.

La clase recupera la cadena de conexión sin ningún problema. Sin embargo, cuando la clase intenta recuperar cualquier configuración de aplicación, el administrador de configuración siempre devuelve null . ¿Que esta pasando aqui?

Editar 1

Pensé que tal vez sería una buena idea intentar cargar algunas configuraciones en el proyecto de prueba para ver qué sucede. Intenté cargar la configuración en la prueba de la unidad inmediatamente antes de llamar al código que crea una instancia de la clase en el proyecto externo. Mismo resultado, nada. Supongo que puedo excluir el otro proyecto de la ecuación por el momento.

Aquí hay un extracto de mi archivo de configuración:

<configSections> <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="MyNamespace.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </sectionGroup> </configSections> ... <applicationSettings> <MyNamespace.Properties.Settings> <setting name="Bing_Key" serializeAs="String"> <value>...</value> </setting> </MyNamespace.Properties.Settings> </applicationSettings>

Y aquí es cómo estoy tratando de cargar la configuración:

string test = System.Configuration.ConfigurationManager.AppSettings["Bing_Key"];


Considere refactorizar su código que accede a la configuración para usar un contenedor. Luego puede escribir simulacros para la clase contenedora y no tener que lidiar con la importación del archivo de configuración para la prueba.

En una biblioteca que sea común a ambos, tenga algo como esto:

public interface IConfigurationWrapper { string GetValue(string key); bool HasKey(string key); }

Luego, en las bibliotecas que necesitan acceder a la configuración, inyecte una instancia de este tipo de interfaz en la clase que necesita leer la configuración.

public class MyClassOne { private IConfigurationWrapper _configWrapper; public MyClassOne(IConfigurationWrapper wrapper) { _configWrapper = wrapper; } // end constructor public void MethodThatDependsOnConfiguration() { string configValue = ""; if(_configWrapper.HasKey("MySetting")) { configValue = _configWrapper.GetValue("MySetting"); } } // end method } // end class MyClassOne

Luego, en una de sus bibliotecas, cree una implementación que dependa del archivo de configuración.

public class AppConfigWrapper : IConfigurationWrapper { public string GetValue(string key) { return ConfigurationManager.AppSettings(key); } public bool HasKey(string key) { return ConfigurationManager.AppSettings.AllKeys.Select((string x) => x.ToUpperInvariant()).Contains(key.ToUpperInvariant()); } }

Luego, en el código que llama a tu clase.

//Some method container MyClassOne dataClass = new MyClassOne(new AppConfigWrapper()); dataClass.MethodThatDependsOnConfiguration();

Luego, en tu prueba, estás libre de la servidumbre por dependencia. :) Puedes crear una versión falsa que implemente IConfigurationWrapper y pasarla para tu prueba, donde codificas los valores de retorno de las funciones GetValue y HasKey , o si estás usando una biblioteca HasKey como Moq:

Mock<IConfigurationWrapper> fakeWrapper = new Mock<IConfigurationWrapper>(); fakeWrapper.Setup((x) => x.GetValue(It.IsAny<string>)).Returns("We just bypassed config."); MyClassOne testObject = new MyClassOne(fakeWrapper.Object); testObject.MethodThatDependsOnConfiguration();

Aquí hay un artículo que cubre el concepto (aunque, para formularios web, pero los conceptos son los mismos): http://www.schwammysays.net/how-to-unit-test-code-that-uses-appsettings-from-web-config/


Usted mencionó la configuración en las propiedades del proyecto. Vea si puede acceder a la configuración de esta manera:

string test = Properties.Settings.Default.Bing_Key;

Es posible que deba obtener el ensamblaje de ejecución donde se define el archivo de configuración del proyecto, pero intente esto primero.

EDITAR

Cuando se usa el archivo de configuración de proyecto de Visual Studio, agrega cosas a tu app.config y crea el app.config si no está presente. ¡ConfigurationManager NO PUEDE tocar estas configuraciones! Solo puede obtener este archivo project.settings generado específico mediante el uso del método estático anterior. Si desea utilizar ConfigurationManager, deberá escribir a mano su app.config. Agregue su configuración de esta manera:

<appSettings> <add key="bing_api" value="whatever"/> </appSettings>


Y luego gritó "NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO".

Cite: Tengo un proyecto de prueba de unidad C # con la configuración de la aplicación en el archivo app.config. Estoy probando una clase que existe en un proyecto diferente. Esa clase depende de ambos, ConfigurationManager.AppSettings y ConfigurationManager.ConnectionStrings.

Tu no haces esto ¡¡¡¡SIEMPRE!!!! ¿Por qué? porque ahora has creado una dependencia. En su lugar, use la inyección de dependencia para que la clase pueda hacer su trabajo sin tener que acceder al archivo de configuración que pertenece a la aplicación.