2010-11-24 13 views
6

Estoy usando un contenedor DI y quiero hacer pruebas de unidad MSTest (VS 2010) con instancias resueltas desde el contenedor.MSTest TestMethod Dependency Injection

Me gustaría obtener estas instancias inyectadas en mi TestMethod o al menos en mi TestClass. es posible?

En este momento, mis TestMethods llaman directamente al container.Resolve<T>(xxx), que prefiero evitar para que mi prueba de inyección sea más realista.

¿Alguien tiene experiencia con esto?

Gracias de antemano.

Respuesta

6

La instanciación de la clase de prueba ocurre profundamente en las clases internas del marco MSTest, por lo que inyectar dependencias en ella sería una tarea desafiante.

5

La razón principal, para mí, para escribir código de acuerdo con el patrón de Inyección de Dependencia y el uso de marcos IoC es obtener código comprobable. Sin embargo, usar un contenedor IoC en tu código de prueba obtendrá el resultado opuesto. De su pregunta, puedo ver que ya está experimentando esto.

Este es especialmente el problema cuando se utiliza el patrón Localizador de servicios (SL) en lugar del patrón de Inyección de dependencias (DI). Con el patrón SL, una clase llama al contenedor IoC (o una abstracción de dicho contenedor) directamente, en lugar de suministrar a la clase las dependencias que necesita (mediante la inyección de constructor). Debido a que las clases llaman directamente al contenedor, también necesita configurar ese contenedor en su entorno de prueba. Esto es doloroso porque la configuración de prueba o los objetos falsos a menudo se vuelven muy complejos, porque a menudo se desea influenciar el comportamiento de un falso por prueba, mientras se mantienen las cosas seguras, porque los frameworks de prueba pueden ejecutar tus pruebas en paralelo (MSTest lo hace). Sé que escribí algún código de prueba loco seguro para subprocesos en el pasado, antes de descubrir que lo estaba haciendo todo mal :-(.

Por lo tanto, debe usar el patrón DI en el código de la aplicación y en sus pruebas debería conectar esas dependencias manualmente. Por ejemplo, cuando se realizan pruebas para una clase HomeController que depende de una clase ICustomerService, normalmente debe tener un método de fábrica CreateController() o CreateValidController en su clase de prueba que centralice la creación de ese HomeController. escribiendo esas dependencias en cada prueba y creando así una pesadilla de mantenimiento en su código de prueba. En este método de fábrica, inyecte por ejemplo una clase FakeCustomerService manualmente, haciendo algo como esto:

private static HomeController CreateController(
    InMemoryDataMapper mapper) 
{ 
    var uowFactory = new FakeNorthwindUnitOfWorkFactory() 
    { 
     UnitOfWork = new NorthwindUnitOfWork(mapper); 
    }; 

    return new HomeController(new FakeCustomerService(uowFactory)); 
} 

El aspecto de un método de fábrica como este, por supuesto, depende (sin juego de palabras) de cómo se ve la estructura de dependencia del HomeController.

Para resumir, no intente hacer la inyección de dependencia en su código de prueba de la misma manera que lo que quiere hacer en el código de su aplicación. Los marcos de prueba no solo hacen que sea muy difícil hacer esto, sino que debe configurar su marco de trabajo de IoC para su entorno de prueba, en cuyo caso se dirigirá al error. Lamentablemente, hablo por experiencia.

+0

No estoy usando un patrón SL, afortunadamente ... solo inyección de constructor. Pensé que recuerdo haber buscado en Google esa pregunta exacta en pruebas paralelas porque tenía la misma preocupación y porque MSBuild no ejecuta pruebas en paralelo de manera predeterminada, pero probablemente estoy equivocado. – Jeff

+1

Entonces, ¿debería duplicar el conocimiento de la dependencia Y la configuración de por vida en todo mi código de prueba? En otras palabras, digamos que tengo un componente que es un singleton en el contenedor y luego debería ser inyectado en un constructor de 5 componentes transitorios que son necesarios para una prueba.Necesito hacer una configuración para esa prueba que sabe instanciar manualmente la instancia del singleton y mantenerla como singleton para inyectarla en cada componente dependiente que instanciamos manualmente. ¿Qué pasa si el componente cambia para no ser un singleton? Tengo que volver a escribir todo el código de configuración de prueba para esto? – Jeff

+0

¿Y qué hay de probar la disponibilidad de componentes o servicios para ser inyectados en constructores de instancias? Si hago la creación de instancias manualmente, me pierdo la prueba de esta pieza clave de funcionalidad. Lo considero clave, porque mantener el estado suele ser una de las partes más delicadas de la programación y, si no estoy probando la disponibilidad de los componentes, me estoy perdiendo la oportunidad de probar la validez de la gestión estatal, ¿no? Una de mis creencias más fuertes en programación es DRY. Más específicamente, "¡No mantengas el estado en dos lugares!". – Jeff

Cuestiones relacionadas