理解为什么我们使用反转控制容器进行单元测试

时间:2014-09-29 13:34:24

标签: c# dependency-injection ninject inversion-of-control

我目前正在考虑将Ninject纳入我的单元测试中。通过与早期问题相关的一些非常聪明的帖子(What is Ninject and when do you use it?http://martinfowler.com/articles/injection.html);我想我得到了一些核心概念,但是如果它的应用程序我正在努力解决一些问题。

大多数情况下,当IOC包含器出现时,它与将它们合并到单元测试中有关。但是,从实际的角度来看,在我的单元测试中使用像Ninject这样的框架是否有意义,如果我还没有将它合并到我的实际代码库中呢?

以下示例的例子(摘自James Bender的C#专业测试驱动开发:使用TDD开发真实世界的应用程序)

[TestFixture]
public class PersonServiceTests
{
    [Test]
    public void ShouldBeAbleToCallPersonServiceAndGetPerson()
    {
        var expected = new Person {Id = 1, FirstName = “John”, LastName = “Doe”};
        var kernel = new StandardKernel(new CoreModule());
        var personService = kernel.Get < PersonService > ();
        var actual = personService.GetPerson(expected.Id);
        Assert.AreEqual(expected.Id, actual.Id);
        Assert.AreEqual(expected.FirstName, actual.FirstName);
        Assert.AreEqual(expected.LastName, actual.LastName);
    }
}

使用Ninject编写我的测试如何改善我的生活(或任何继承我的代码的可怜的开发人员),而不是仅仅编写我的测试:

[TestFixture]
public class PersonServiceTests
{
    [Test]
    public void ShouldBeAbleToCallPersonServiceAndGetPerson()
    {
        var expected = new Person {Id = 1, FirstName = “John”, LastName = “Doe”};
        var personService = new PersonService();
        var actual = personService.GetPerson(expected.Id);
        Assert.AreEqual(expected.Id, actual.Id);
        Assert.AreEqual(expected.FirstName, actual.FirstName);
        Assert.AreEqual(expected.LastName, actual.LastName);
    }
}

我将依赖倒置原则合并到我的代码中;我认为IOC容器的价值是减少冗余/集中代码的一种方式,这些代码与我的类的实例化方式有关(因为尊重依赖性反转原则)。但是,如果我不想在我的代码中使用IOC容器,那么将Ninject这样的东西仅作为我的单元测试框架堆栈的一部分是否可行?

1 个答案:

答案 0 :(得分:5)

为什么要在测试中使用DI框架?您的对象图表难以撰写吗?

我个人认为你最好只是让测试明确地创建它们的依赖关系,然后注入模拟或存根将在测试中显式并且非常明显。

它还隐藏了创建复杂依赖关系层次结构的任何问题。在测试中创建所有对象意味着您必须感受到创建这些依赖项的痛苦,并可能激励您改进设计。

我不认为使用DI框架可以在这种情况下购买任何东西,除了模糊测试所依赖的依赖项。

集成测试可能是一个不同的故事,但对于单元测试......