Tendré que estar en desacuerdo con ambas respuestas. TheCodeKing, es completamente legítimo usar la interfaz IoC directamente. Un ejemplo podría ser una fábrica de controladores en el proyecto ASP.NET, donde se podría hacer una resolución no trivial usando múltiples métodos en la interfaz
IUnityContainer
.
Hmm ... con labdas de inyección de fábrica automática, uno nunca tiene que probar la interfaz IoC directamente. Simplemente podría pasar un lambda y verificar que se llame con los parámetros correctos.
Budda, debe nunca llevar un contenedor IoC en su unidad de prueba. Las dependencias deben ser inyectadas manualmente.
A continuación se muestra la solución que uso. Básicamente, creé una capa de abstracción sobre IUnityContainer
e implementé una clase simple que delega en IUnityContainer
. Debido a que mi interfaz no contiene métodos de extensión, puedo simularlo fácilmente.
public interface IDIContainer {
void RegisterType<TFrom>() where TFrom : class;
void RegisterType<TFrom, TTo>() where TTo : TFrom;
void RegisterType<TFrom, TTo>(string name) where TTo : TFrom;
void RegisterType(Type from, Type to);
void RegisterType(Type from, Type to, string name);
void RegisterInstance<TFrom>(TFrom instance) where TFrom : class;
T Resolve<T>();
T Resolve<T>(string name);
IEnumerable<T> ResolveAll<T>();
bool IsRegistered<TFrom>(string name) where TFrom : class;
bool IsRegistered<TFrom>() where TFrom : class;
}
public class DIContainer : IDIContainer {
IUnityContainer m_Container = new UnityContainer();
#region IDIContainer Members
public void RegisterType<TFrom>() where TFrom : class {
m_Container.RegisterType<TFrom>();
}
public void RegisterType<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>();
}
public void RegisterType<TFrom, TTo>(string name) where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(name);
}
public void RegisterType(Type from, Type to) {
m_Container.RegisterType(from, to);
}
public void RegisterType(Type from, Type to, string name) {
m_Container.RegisterType(from, to, name);
}
public void RegisterInstance<TFrom>(TFrom instance) where TFrom : class {
m_Container.RegisterInstance<TFrom>(instance);
}
public T Resolve<T>() {
return m_Container.Resolve<T>();
}
public IEnumerable<T> ResolveAll<T>() {
return m_Container.ResolveAll<T>();
}
public T Resolve<T>(string name) {
return m_Container.Resolve<T>(name);
}
public bool IsRegistered<TFrom>(string name) where TFrom : class {
return m_Container.IsRegistered<TFrom>(name);
}
public bool IsRegistered<TFrom>() where TFrom : class {
return m_Container.IsRegistered<TFrom>();
}
#endregion
}
Ahora, reescribir su clase para utilizar IDIContainer
:
public class MyManager
{
public MyManager(IDIContainer container) : base(container) { }
public IResult DoJob(IData data)
{
IMyLog log = MyContainer.Resolve<IMyLog>();
... use log.Id ...
MyContainer.Resolve<...>();//usage for other purposes...
}
}
y reescribir la prueba unitaria de este modo:
[TestClass]
public class Test {
[TestMethod]
public void TestDoJob() {
Mock<IMyLog> mockLog = new Mock<IMyLog>();
Mock<IDIContainer> containerMock = new Mock<IDIContainer>();
//Setup mock container to return a log mock we set up earlier
containerMock.Setup(c=>c.Resolve<IMyLog>()),Returns(mockLog);
//Verify that all setups have been performed
containerMock.VerifyAll();
}
}
Dependencias en el contenedor IoC son un antipatrón. Intenta restringir el contenedor a una clase de nivel superior y haz que cree tus otros objetos. Como @TheCodeKing sugiere, las fábricas de automóviles pueden ayudar. Consulte http://kozmic.pl/2010/06/20/how-i-use-inversion-of-control-containers/ – TrueWill