9

Tengo una biblioteca de clase que quiero probar en una unidad usando el marco de prueba de la unidad Microsofts. Algunas de las clases que quiero probar están configuradas usando la configuración de la aplicación. Esta configuración se define dentro del archivo Settings.settings con alcance de aplicación y valores predeterminados adecuados. Cuando la aplicación utiliza la biblioteca, esta configuración puede ser anulada en el archivo App.Config. Si no, se usan los valores predeterminados. Así es exactamente como quiero que sea.Modificación de la configuración de la aplicación en pruebas unitarias

En algunos de mis casos de prueba quiero probar combinaciones especiales de valores de configuración pero no sé cómo cambiar los valores vistos por la clase bajo prueba del código de prueba de la unidad. Estas configuraciones siempre tendrán su valor predeterminado cargado de los atributos de la clase generada por el código.

En mi clase de biblioteca puedo acceder a la configuración de la siguiente manera:

var mySetting1 = Settings.Default.MySetting1; 
var mySetting2 = Settings.Default.MySetting2; 

¿Cómo modificar estos ajustes en una unidad de prueba antes de que el ajuste se accede por la clase que se está probando? Hacer que la clase de configuración interna sea accesible mediante la prueba unitaria no resuelve el problema ya que las configuraciones tienen alcance de aplicación y son propiedades de solo lectura en la clase de configuración.

Respuesta

14

Después de la espeleología en las clases ApplicationSettingsBase y asociados se me ha ocurrido con esta solución a mi problema. No es particularmente hermoso, pero sin duda hace el trabajo.

La clase de configuración generada por código es interna para el proyecto de la biblioteca de clase y debe ser accesible para el proyecto de prueba de la unidad. Agregue el atributo [assembly: InternalsVisibleTo("UnitTestAssemblyName")] al AssemblyInfo.cs en el proyecto de biblioteca de clase.

La configuración se carga de forma holgazana desde los atributos en la clase de configuraciones cuando se accede a un valor. El primer paso es hacer una lectura "ficticia" de una configuración para forzar esta carga diferida. Cuando prueba una unidad, quiere evitar que los valores de configuración cambiados en una prueba afecten a otra, por lo tanto, es necesario "restablecer" la configuración antes de cargarla. Eso se puede hacer usando el método Reload(). Este código se coloca en el método initialize prueba:

Settings.Default.Reload(); 
var dummy = Settings.Default.MySetting1; 

Los valores subyacentes ahora existen y se pueden ajustar en cada método de prueba. Recuerde que debe utilizar el tipo correcto como los captadores de código generada llevará a cabo un reparto:

Settings.Default.PropertyValues["MyStringSetting1"].PropertyValue = "Foobar"; 
Settings.Default.PropertyValues["MyDoubleSetting2"].PropertyValue = 3.1416D; 
+0

+1 para la solución alternativa del Accesor de Recarga + Propiedad. –

+0

Gracias por esto, nunca lo hubiera descubierto por mi cuenta. –

5

Crearía una clase contenedora alrededor de la clase Settings y luego pasaría esa envoltura. Entonces puede burlarse de su clase de configuración con facilidad.

La única otra cosa que se me ocurre es la opción un poco más liviana y más fácil de simular que su archivo de configuración implemente una interfaz que refleje todas sus configuraciones. No es muy diferente para la persona que llama, pero tendrá menos plomería para agregar nuevas configuraciones.

Tampoco es fantástico, y es un dolor tener que hacerlo para el código generado automáticamente, pero parece que eso es lo que estamos atrapados en lo que puedo decir si realmente desea eliminar la dependencia de la archivo de configuración

E.g. para un archivo de configuración que contiene un entorno de aplicación de cuerdas y un entorno int usuario:

internal sealed partial class Settings : IMySettings { 

    /* 
    * here be auto-generate code (and dragons!) 
    */ 
} 

internal interface IMySettings 
{ 
    string ApplicationSetting 
    { 
     get; 
    } 

    string UserSetting 
    { 
     get; 
     set; 
    } 
} 
+0

yo más bien evitar la inyección de configuración ya que tengo muchas bibliotecas y el número de dependencias para inyectar crece mucho cuando me muevo por la jerarquía de la dependencia .Además, envolver clases que son código generado por Visual Studio es tedioso. Esperaba una solución que no fuera DI pura, pero funcionaría bien con la configuración de la aplicación en .NET. –

+0

Lamentablemente, no creo que haya ninguno, lo mejor que puede hacer es configurar el usuario, pero la configuración de la aplicación no cambiará fuera del archivo. La única otra cosa que se me ocurre en este momento es usar una interfaz, un poco más ligera, pero igual, como dices, DI puro. –

Cuestiones relacionadas