使用IoC进行单元测试

时间:2009-09-23 13:02:46

标签: c# unit-testing mocking inversion-of-control

如何将IoC容器用于单元测试?使用IoC在大型解决方案(50多个项目)中管理模拟是否有用?任何经历?任何C#库在单元测试中都能很好地使用它吗?

4 个答案:

答案 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)

使用能够解析未注册/未知服务的容器,例如SimpleInjectorDryIoc(我的)可以为尚未实现的接口返回模拟。

这意味着您可以通过第一个简单的实现及其模拟的依赖项开始开发,并在您进步时用真实的东西替换它们。