如何将IoC容器用于单元测试?使用IoC在大型解决方案(50多个项目)中管理模拟是否有用?任何经历?任何C#库在单元测试中都能很好地使用它吗?
答案 0 :(得分:122)
一般来说,单位测试不需要DI容器,因为单元测试完全是分离责任。
考虑使用Constructor Injection
的类public MyClass(IMyDependency dep) { }
在整个应用程序中,可能隐藏在IMyDependency
后面的巨大依赖关系图,但在单元测试中,您将其全部展平为Test Double。
您可以使用Moq或RhinoMocks等动态模拟生成Test Double,但不是必需的。
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
在某些情况下,auto-mocking container可能很不错,但您不需要使用生产应用程序使用的相同DI容器。
答案 1 :(得分:17)
如何将Ioc容器用于单元测试?
IoC将强制执行编程范例,使单独测试(即使用模拟)变得更容易:使用接口,没有new(),没有单例......
但是使用IoC容器进行测试并不是真正的要求,它只会提供一些设施,例如:注射嘲笑,但你可以手动完成。
使用IoC在大型解决方案(50多个项目)中管理模拟是否有用?
我不确定使用IoC管理模拟是什么意思。无论如何,IoC容器通常可以做的不仅仅是在测试时注入模拟。如果你有可靠的IDE支持使重构成为可能,为什么不使用它呢?
有经验吗?
是的,在一个巨大的解决方案中,您比以往任何时候都更需要一个不容易出错且重构不利的解决方案(即通过类型安全的IoC容器或良好的IDE支持)。
答案 2 :(得分:16)
我经常在测试中使用IoC容器。当然,它们不是纯粹意义上的“单元测试”。 IMO他们更加BDDish并促进重构。测试可以让你有信心进行重构。写得不好的测试可能就像在你的代码中注入水泥一样。
请考虑以下事项:
[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
[Test]
public void Should_save_image()
{
container.ConfigureMockFor<IFileRepository>()
.Setup(r => r.Create(It.IsAny<IFile>()))
.Verifiable();
AddToGallery(new RequestWithRealFile());
container.VerifyMockFor<IFileRepository>();
}
private void AddToGallery(AddBusinessImage request)
{
container.Resolve<BusinessPublisher>().Consume(request);
}
}
将图像添加到图库时会发生一些事情。调整图像大小,生成缩略图,并将文件存储在AmazonS3上。通过使用容器,我可以更容易地隔离我想要测试的行为,在这种情况下是持久化部分。
使用此技术时,自动模拟容器扩展会派上用场: http://www.agileatwork.com/auto-mocking-unity-container-extension/
答案 3 :(得分:2)
使用能够解析未注册/未知服务的容器,例如SimpleInjector,DryIoc(我的)可以为尚未实现的接口返回模拟。
这意味着您可以通过第一个简单的实现及其模拟的依赖项开始开发,并在您进步时用真实的东西替换它们。