我将不得不不同意这两个答案。TheCodeKing,直接使用IoC接口是完全合法的。IUnityContainer
一个例子可能是 ASP.NET 项目中的控制器工厂——其中一个可能在接口上使用多种方法进行非平凡的解析。
嗯...使用自动工厂注入 labdas,无需直接对 IoC 接口进行单元测试。您可以只传递一个 lambda 并验证它是否使用正确的参数被调用。
Budda,你永远不应该在你的单元测试中引入 IoC 容器。必须手动注入依赖项。
以下是我使用的解决方案。我基本上创建了一个抽象层IUnityContainer
并实现了一个简单的类,它委托给IUnityContainer
. 因为我的接口不包含扩展方法,所以我可以轻松地模拟它。
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
}
现在,重写你的类以使用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...
}
}
并像这样重写单元测试:
[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();
}
}