Мне придется не соглашаться с обоими ответами.TheCodeKing, вполне законно использовать интерфейс IoC напрямую.Одним из примеров может быть фабрика контроллеров в проекте ASP.NET - где можно выполнить нетривиальное разрешение, используя несколько методов на интерфейсе IUnityContainer
.
Хмм ... с автоматическим вводом labdas,никогда не нужно тестировать интерфейс IoC напрямую.Вы можете просто передать лямбду и убедиться, что она вызывается с правильными параметрами.
Будда, вы должны никогда ввести контейнер 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();
}
}