关于c#:了解为什么我们使用反转控制容器进行单元测试

Understanding why we use Inversion of control containers for unit testing

我目前正在考虑将ninject合并到我的单元测试中。在浏览一些与之前问题相关的非常聪明的帖子时(Ninject是什么?你什么时候使用它?,http://martinfowler.com/articles/injection.html);我想我得到了一些核心概念,但是我正在努力研究一些if应用程序。

大多数情况下,当提到IOC containers时,它与将它们合并到单元测试中有关。但是,从实践的角度来看,如果我还没有将Ninject这样的框架纳入我的实际代码库,那么在我的单元测试中使用它是否有意义?

举例来说,下面的例子(摘自詹姆斯·本德的专业测试驱动开发和C:用TDD开发现实世界中的应用程序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[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编写测试如何改善我的生活(或继承我代码的任何可怜的开发人员),而不是将我的测试编写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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这样的东西单独用作我的单元测试框架堆栈的一部分是否可行?


为什么要在测试中使用DI框架?你的对象图很难组合吗?

我个人认为,最好是让测试显式地创建它们的依赖关系,因为注入mock或stub在测试中是显式的,并且非常可见。

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

在这种情况下,我不认为使用DI框架可以为您带来任何好处,除了模糊测试所具有的依赖性。

集成测试可能是另一回事,但对于单元测试…