依赖注入解析和单元测试

时间:2009-05-04 13:30:26

标签: c# .net unit-testing dependency-injection ioc-container

我正在尝试学习依赖注入,并在单元测试应用程序时遇到了问题。

我正在编写一个控制台应用程序,并在Main()中创建并初始化容器,它在get-property中以Program.Container形式提供,因此我的应用程序中的任何地方都可以调用{{1} }。

我有一个像这样的ServiceValidator类:

Program.Container.Resolve<..>()

在另一个课程中我使用

public class ServiceValidator
{
    private readonly IConfiguration _configuration;
    private readonly IService _service;

    public ServiceValidator(IConfiguration configuration, IService service)
    {
        _configuration = configuration;
        _service = service;
    }

这是对ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>(); serviceValidator.VerifyVersion(); 的调用导致我在单元测试中遇到问题,因为它尚未设置。

在容器上调用resolve是不好的做法?我可以在Program.Container.Resolve中创建ServiceValidator实例并传递对象,但这似乎很愚蠢,因为它会导致很多参数传递给下一个方法。

所以我想在类中调用Resolve是可以接受的,但是必须为单元测试配置容器。如果我将容器移动到Program类以外的其他地方,我该怎么做?你会推荐什么?

如果重要,我正在使用Unity和C#

谢谢: - )

5 个答案:

答案 0 :(得分:8)

  

在容器上调用resolve是不好的做法?我可以在Main()中创建ServiceValidator实例并传递对象,但这似乎很愚蠢,因为它会导致很多参数传递给下一个方法。

当你一直使用依赖注入时,你不需要将大量参数传递给对象。每个对象的构造函数应仅具有它本身直接使用的那些依赖项作为参数 - 它不会知道其直接依赖项的传递依赖性。

因此,如果您有一个需要ServiceValidator的类X,那么类X将具有ServiceValidator类型的构造函数参数。然后,如果某个类Y使用类X,那么类Y将具有类型X的构造函数参数。请注意,Y 对ServiceValidator一无所知,因此您不需要将ServiceValidator从一个类传递给另一个 - 使用它的唯一地方是构建X时,这通常由DI框架完成,或者只在手工编写的工厂中的一个地方完成。

一些链接以获取更多信息:

答案 1 :(得分:1)

我通常允许调用来解决像main这样的容器中的依赖关系,尽管我仍然试图将它们保持在最低限度。然后我做的是在测试类的初始化方法中配置容器。我已经使用假实现初始化了任何需要调用容器的测试类。

不会调用任何需要容器的任何东西的测试类然后能够忽略它并且不使用假货。我经常在那些情况下使用模拟。

我也使用Microsoft Service Locator,这样我所依赖的依赖关系来自.NET Framework而不是特定容器。这使我可以在路上使用任何我想要的东西,甚至是自酿的容器。

答案 2 :(得分:0)

您可以使用静态类作为容器的初始化程序。像BootStrapper.cs之类的东西就好了。然后,您可以在代码和测试中引用类方法。

答案 3 :(得分:0)

你在技术上做的是你班上的服务地点。

我记得有一段时间读过这篇文章:

http://martinfowler.com/articles/injection.html

对于我的课程,我从不尝试在其中使用Resolve。我需要时通过容器创建对象。对于单元测试,我要么使用一些模拟库和存根类。

答案 4 :(得分:0)

问题在于您正在尝试测试Main方法。这种方法几乎不可能进行单元测试。

我认为最好不要对您的Main方法进行单元测试,因为:

  • 现代单元测试的重点是设计
  • 您应该最小化单元测试中对配置的依赖性。可以使用冒烟或集成测试来测试配置。