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

本文关键字:单元测试 控制 我们 为什么 | 更新日期: 2023-09-27 18:25:06

我目前正在考虑将Ninject合并到我的单元测试中。在浏览一些与早期问题相关的非常聪明的帖子时(什么是Ninject,你什么时候使用它,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);
    }
}

当我将依赖反转原则融入到我的代码中时;我认为IOCContainers的价值是减少与类实例化方式相关的冗余/集中代码的一种方式(这是尊重依赖反转原则的结果)。然而,如果我不想在代码中使用IOC容器,那么将像Ninject这样的东西单独用作单元测试框架堆栈的一部分是否实用?

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

为什么要在测试中使用DI框架?你的对象图有那么难写吗?

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

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

在这种情况下,我不认为使用DI框架能为你带来任何好处,除了混淆你的测试所具有的依赖性。

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