使用Simple Injector使用不同的配置

时间:2012-12-07 17:01:44

标签: c# dependency-injection inversion-of-control simple-injector

我正在使用Simple Injector依赖注入框架,它看起来很酷很好。但是在构建配置并使用它之后,现在我想知道如何从一种配置更改为另一种配置。

场景:让我们假设我在全局Asax中设置了一个配置,我在那里有公共和全局Container实例。现在我想做一些测试,我希望他们使用模拟类,所以我想改变配置。

当然,我可以构建另一个配置并将其分配给默认创建的全局Container,这样每次运行测试时都会设置备用配置。但是在这样做的时候,尽管我处于开发环境中,Container对每个人都有所改变,即使对于正常的请求也是如此。我知道我正在测试这个环境,这应该不重要,但我觉得这不是这样做的方式......我想知道如何以正确的方式从一种配置转换到另一种配置。 / p>

1 个答案:

答案 0 :(得分:9)

进行单元测试时,根本不应使用容器。只需通过调用其构造函数并为其提供适当的模拟对象来创建被测试的类。

过去曾经帮助过我的一个模式是使用一个简单的特定于测试类的工厂方法。此方法集中创建要测试的类,并最小化在测试类的依赖项发生更改时需要进行的更改量。这就是这种工厂方法的样子:

private ClassUnderTest CreateValidClassUnderTest(params object[] dependencies)
{
    return new ClassUnderTest(
        dependencies.OfType<ILogger>().SingleOrDefault() ?? new FakeLogger(),
        dependencies.OfType<IMailSender>().SingleOrDefault() ?? new FakeMailer(),
        dependencies.OfType<IEventPublisher>().SingleOrDefault() ?? new FakePublisher());
}

对于集成测试,使用容器更常见,并交换容器的一些依赖项。尽管如此,这些集成测试不会使用您在application_start中创建的容器,但在这种情况下,每个集成测试很可能都有自己的新容器实例,因为每个测试都应该独立运行。即使您确实使用了application_start中的单个容器,您的集成测试也是从单独的项目运行的,不会干扰正在运行的应用程序。

虽然每个集成测试都应该获得自己的容器实例(如果有的话),但您仍然希望尽可能多地重用容器配置代码。这可以通过将此代码提取到一个方法来完成,该方法在调用时返回新配置的容器实例,或者配置提供的容器实例(并且不返回任何内容)。此方法通常应执行不完整的配置,调用方(测试或全局asax)应添加缺少的配置。

提取此代码:允许您拥有部分共享相同配置的多个终端应用程序;允许您在集成测试中验证容器;并允许您添加需要由集成测试模拟的服务。

为了简化生活,Simple Injector允许您用新的注册替换现有注册(例如模拟注册)。您可以按如下方式启用它:

container.Options.AllowOverridingRegistrations = true;

但要小心!此选项可以隐藏您不小心覆盖注册的事实。根据我的经验,在大多数情况下,建立一个不完整的容器并在之后添加缺少的注册而不是覆盖它们会好得多。或者,如果您决定覆盖,请在最后一刻启用该功能,以防止任何意外的错误配置。