组合根是否需要单元测试?

时间:2013-08-28 13:07:03

标签: c# dependency-injection compositionroot

我试图找到答案,但似乎没有直接讨论过很多。我有一个我的应用程序的组合根,我创建一个DI容器并在那里注册所有内容,然后解决所有依赖项所需的顶级类。由于这一切都在内部发生 - 因此很难对组合根进行单元测试。你可以做虚拟方法,受保护的字段等等,但我不是为了能够进行单元测试而引入这些东西的忠实粉丝。其他类没有大问题,因为它们都使用构造函数注入。所以问题是 - 根本测试组合根是否有意义?它确实有一些额外的逻辑,但并不多,在大多数情况下,在应用程序启动期间会弹出任何故障。 我有一些代码:

public void Initialize(/*Some configuration parameters here*/)
    {
        m_Container = new UnityContainer();

        /*Regestering dependencies*/

        m_Distributor = m_Container.Resolve<ISimpleFeedMessageDistributor>();
    }

    public void Start()
    {
        if (m_Distributor == null)
        {
            throw new ApplicationException("Initialize should be called before start");
        }

        m_Distributor.Start();
    }

    public void Close()
    {
        if (m_Distributor != null)
        {
            m_Distributor.Close();
        }
    }

1 个答案:

答案 0 :(得分:9)

  

根本测试组合物根本没什么意义吗?

您想知道您的申请是否写得正确吗?你可能这样做,这就是你编写测试的原因。出于同样的原因,你应该测试你的作文根。

然而,这些测试专门针对系统布线的正确性。您不想测试单个类是否正常运行,因为某些单元测试已经涵盖了这一点。您也不想测试类是否以正确的顺序调用其他类,因为这是您要在常规集成测试中测试的内容(调用MVC控制器并查看调用是否在数据库中结束是此类集成测试的示例)。

以下是您可能应该测试的一些内容:

  • 可以解决所有顶级课程。这可以防止您必须单击应用程序中的所有屏幕,以确定是否所有内容都正确连接。
  • 该组件仅依赖于同等或更长时间的服务。当组件依赖于配置了较短生命周期的另一个组件时,该组件将“提升”该依赖关系的生命周期,这通常会导致难以重现和修复的错误。检查此类问题很重要。这种类型的错误也被称为生活方式不匹配或俘虏依赖。
  • 正确应用了对应用程序正确性至关重要的装饰器和其他拦截机制。装饰器可以例如添加交叉处理问题,例如事务处理,安全性和缓存,这些问题以正确的顺序执行是很重要的(例如,必须在查询缓存之前执行安全检查),但是很难使用正常的集成测试对此进行测试。

但是,为了能够这样做,您需要verifiable DI configuration

请注意not everybody分享这个意见。但我的经验是,验证配置的正确性非常有价值。

因此,使用一些IoC容器测试这些东西可能会遇到挑战,而其他IoC容器可以帮助您解决这个问题(但Unity很可能缺少大部分功能)。

某些容器甚至可以调用某种验证方法来验证配置。 “验证”的含义因每个库而异。例如,Simple Injector(我是Simple Injector的主要开发人员)有一个Verify方法,它将简单地迭代所有注册并在每个注册上调用GetInstance以确保可以创建每个实例。我总是建议用户尽可能在他们的作文根中调用Verify。例如,这并不总是可行的,因为当配置变大时,对Verify的调用会导致应用程序启动太慢。但是,它仍然是一个很好的起点,可以消除很多痛苦。如果需要很长时间,您可以随时将呼叫转移到自动测试。

对于Simple Injector,这只是一个开始。 Simple Injector包含Diagnostic Services,用于检查容器是否存在常见的错误配置,例如前面提到的“生活方式不匹配”​​。

所以你应该绝对想要测试,但我不确定是否要将这些测试称为“单元测试”,尽管我设法单独运行这些测试(无需访问数据库或Web服务)。