2009-06-10 31 views
19

Escenario. Idioma C#, Pruebas unitarias usando VS2008 Marco de pruebas de unidadesPrueba de unidad Clases estáticas

Tengo una clase estática con un constructor estático y 2 métodos. Tengo 4 métodos de prueba escritos para probar toda la clase. My Static Constructor tiene algunas inicializaciones importantes.

Ahora si ejecuto todos los casos de prueba de 4 unidades en tándem, el constructor estático será llamado solo al principio. Al final de cada caso de prueba, no hay tal cosa

llamado destructor estático, por lo que la información de estado en el constructor se lleva al caso de prueba de la próxima unidad también. ¿Cuál es la solución para esto?

Respuesta

11

La solución más simple es agregar un método "Restablecer" a su clase estática, que tendría el mismo comportamiento de destruirlo y reconstruirlo.

Puede haber una razón válida por la que está utilizando una clase estática aquí. Sin embargo, debido a que la estática no juega muy bien con las pruebas unitarias, generalmente busco un diseño alternativo.

0

Bueno, usted no especificó qué idioma estaba usando, pero si hay una manera de abrir su clase estática desde el archivo de prueba, entonces le agregaría un falso destructor, al que puede llamar después cada prueba. De esta forma, el 'destructor' permanece en la clase de prueba y fuera de su código de producción.

0

Puede usar Typemock's Isolator que es capaz de burlar las clases estáticas, por lo que en cada prueba puede "definir" cómo funcionará la estática.

Sin embargo, no es un producto gratuito.

0

Parece que está intentando probar el constructor estático. Esto parece una mala idea.

Considere la posibilidad de extraer la lógica de inicialización en una clase separada (no estática) en su lugar.

Por el bien de la discusión, digamos que su clase estática se llama MySingleton, y digamos que crea una nueva clase llamada MyInitializer, con un método Execute. El constructor estático de MySingleton podría instanciar MyInitializer y llamar a Execute, que hace toda la inicialización.

Entonces su código de producción podría usar MySingleton e ignorar MyInitializer. Sus pruebas, por otro lado, podrían ignorar MySingleton y crear alegremente una nueva instancia MyInitializer para cada prueba, obteniendo un nuevo comienzo cada vez.

1

Sin saber que el uso de la clase al comentar solo el uso es un poco complicado, pero de todas maneras lo intentaré. Para mí, lo anterior suena como un olor más que como un problema de prueba.

Una clase estática (solo como singletons) es básicamente una colección de funciones/variables globales que generalmente es algo malo en oop. Yo diría que tratar de probar el problema de la prueba (aunque probablemente sea el más fácil en este momento) solo soluciona el síntoma, pero no el problema.

me gustaría sugerir a echar un vistazo a la el desing un concidere si realmente necesita la clase estática o si simplemente parecía la forma más fácil de solucionar un problema en el momento

5

me movería la inicialización de el constructor estático a un método que es llamado por el constructor.Al hacer este método interno, puede llamar a este método desde sus pruebas para reiniciar la clase.

public static class MyClass 
{ 
    public static MyClass() 
    { 
     initialize(); 
    } 

    internal static void initialize() 
    { 
     // Do initialization (and cleanup if necessary) 
    } 

    public static void Method1() {} 
    public static void Method2() {} 
} 

Con el fin de llamar a los métodos internos que necesita para utilizar el atributoInternalsVisibleTo, como se describe en this blog.

También puede hacerlo privado, pero luego debe usar el reflejo para llamarlo.

Pero como dijo Andrew Shepherd, también debes comprobar si una clase estática es el mejor diseño de esta clase.

34
Type staticType = typeof(StaticClassName); 
ConstructorInfo ci = staticType.TypeInitializer; 
object[] parameters = new object[0]; 
ci.Invoke(null, parameters); 

de http://colinmackay.scot/2007/06/16/unit-testing-a-static-class/

+21

hey look, una respuesta real a la pregunta en lugar de "no hagas eso". – deltree

+0

Funciona bien, sin embargo tuve que declarar manualmente un constructor estático vacío en la clase (incluso si normalmente no es necesario). –

+1

¿Por qué se usan parámetros para el constructor estático? ¿Podemos llamarlo 'ci.Invoke (null, null);'? – SerG

0

En aras de la exhaustividad, si es necesario restablecer un campo que no es pública/variable de una clase estática, sino que también es posible hacerlo a través de la reflexión.

using System.Reflection; // or Mono.Reflection 

public static class MyClass{ 
    private static string myString; 
} 

var newValue = "Potatoes";    
var field = typeof(MyClass).GetField("myString", BindingFlags.Static | BindingFlags.NonPublic); 
field.SetValue(null, newValue); // the first null is because the class is static, the second is the new value