unit-testing Contenedores / Marcos DI


Ejemplo

Si bien extraer las dependencias de su código para poder inyectarlas hace que su código sea más fácil de probar, empuja el problema hacia la jerarquía y también puede generar objetos que son difíciles de construir. Se han escrito varios marcos de inyección de dependencia / contenedores de inversión de control para ayudar a superar este problema. Éstos permiten registrar mapeos de tipo. Estos registros se utilizan para resolver dependencias cuando se solicita al contenedor que construya un objeto.

Considera estas clases:

public interface ILogger {
    void Log(string message);
}

public class ConcreteLogger : ILogger
{
    public ConcreteLogger()
    {
        // ...
    }
    public void Log(string message)
    {
        // ...
    }
}
public class SimpleClass
{
    public SimpleClass()
    {
        // ...
    }
}

public class SomeProcessor
{
    public SomeProcessor(ILogger logger, SimpleClass simpleClass)
    {
        // ...
    }
}

Para construir SomeProcessor , tanto una instancia de ILogger y SimpleClass son obligatorios. Un contenedor como Unity ayuda a automatizar este proceso.

Primero se debe construir el contenedor y luego se registran las asignaciones. Esto generalmente se hace solo una vez dentro de una aplicación. El área del sistema donde ocurre esto se conoce comúnmente como la Raíz de composición

// Register the container
var container = new UnityContainer();

// Register a type mapping.  This allows a `SimpleClass` instance
// to be constructed whenever it is required.
container.RegisterType<SimpleClass, SimpleClass>();

// Register an instance.  This will use this instance of `ConcreteLogger` 
// Whenever an `ILogger` is required.
container.RegisterInstance<ILogger>(new ConcreteLogger());

Una vez que se configura el contenedor, se puede usar para crear objetos, resolviendo automáticamente las dependencias según sea necesario:

var processor = container.Resolve<SomeProcessor>();