Intento utilizar el kernel DI directamente en mi código lo menos posible, en lugar de confiar en la inyección del constructor (o propiedades en casos seleccionados, como las clases Attribute
). Donde debo, sin embargo, uso una capa de abstracción, de modo que pueda establecer el objeto del núcleo DI, haciéndolo divisible en pruebas unitarias.
Por ejemplo:
public interface IDependencyResolver : IDisposable
{
T GetImplementationOf<T>();
}
public static class DependencyResolver
{
private static IDependencyResolver s_resolver;
public static T GetImplementationOf<T>()
{
return s_resolver.GetImplementationOf<T>();
}
public static void RegisterResolver(IDependencyResolver resolver)
{
s_resolver = resolver;
}
public static void DisposeResolver()
{
s_resolver.Dispose();
}
}
El uso de un patrón de esta manera, se puede establecer el IDependencyResolver
de pruebas unitarias llamando RegisterResolver
con una aplicación simulada o falsa que devuelve cualquier objeto que desee sin tener que cablear módulos completos . También tiene un beneficio secundario de abstraer su código de un contenedor de IoC particular, si elige cambiar a uno diferente en el futuro.
Naturalmente, también le gustaría agregar métodos adicionales al IDependencyResolver
según sus necesidades, solo estoy incluyendo aquí lo básico. Sí, esto requeriría que escribas un envoltorio super simple alrededor del kernel Ninject que implemente IDependencyResolver
también.
La razón por la que desea hacer esto es que las pruebas de su unidad solo deberían probar una cosa y utilizando su contenedor IoC real, está realmente haciendo más ejercicio que la clase bajo prueba, lo que puede generar falsos negativos. que hacen que tus pruebas sean frágiles y (lo que es más importante) sacuden la confianza del desarrollador en su precisión a lo largo del tiempo. Esto puede llevar a la apatía y al abandono de la prueba, ya que es posible que las pruebas fallen pero el software funcione correctamente ("no se preocupe, siempre falla, no es gran cosa").
+1 para el patrón de resolver, sin embargo, REALMENTE intente utilizar la inyección de constructor en su MyClass que requiere IDepend. de esa manera, las pruebas de su unidad ni siquiera necesitan su contenedor IoC. –
¿Por qué no hacer algo más simple como anular enlaces como ese ... var kernel = new StandardKernel (nuevo ProductionModule (config)); kernel.Rebind() .A () .InSingletonScope(); –
Puede anular los enlaces, pero luego sus pruebas también están probando su contenedor DI, junto con la unidad bajo prueba. En algunas situaciones, esto no es un gran problema, pero puede llevar a falsos negativos y erosionar la fe en el conjunto de pruebas, como expliqué en mi respuesta. – krohrbaugh