2

我使用 Specflow 和 WatiN 进行了一些验收测试,但不确定在哪里为我的 IOC 容器 (SimpleServiceLocator) 设置注册。

在我的网站上,注册是在我的 global.asax 上完成的。

在我的测试项目中,我尝试使用 [BeforeScenario] 方法使用以下代码设置它们

var container = new SimpleServiceLocator();
container.Register<ISitecoreLookupAccessor>(
    () => new SitecoreLookupAccessor());

Microsoft.Practices.ServiceLocation.ServiceLocator
    .SetLocatorProvider(() => container);

我在我的应用程序项目中使用了一个对象实例

ISitecoreLookupAccessor accessor =
    ServiceLocator.Current.GetInstance<ISitecoreLookupAccessor>();

但我收到一个错误“对象引用未设置为对象的实例”。因为 ServiceLocator.Current 为 null ...

4

1 回答 1

0

Global.asax 是 ASP.NET 特定的,不会在您的测试项目中运行,因为您的测试运行者无法知道它甚至应该考虑有可能它们可能是 global.asax :-)

换句话说,为了让您能够使用ServiceLocator.CurrentServiceLocator.SetLocatorProvider应该使用该测试项目的有效容器调用 。使用 MSTest 时,有一个AssemblyInitializeAttribute可用于装饰方法。在这种情况下,MSTest 将在执行该程序集中的任何测试方法之前运行该方法。其他测试运行器有不同的机制来执行此操作。

但是,与其在测试项目中配置 Common Service Locator,不如在测试中完全避免使用它要好得多。而是在其构造函数中注入被测类的所有依赖项,并在每个测试的设置阶段执行此操作(为方便起见,您可以将此类被测对象的构造重构为特殊的工厂方法)。防止从ServiceLocator被测类(或应用程序中的任何类)中调用。这样就不需要使用ServiceLocator在您的测试项目中。这将使编写测试变得更加容易,因为您不必在测试程序集中维护 DI 配置(并且对于多个测试项目,您将拥有多个 DI 配置)。我走了这条路,我的测试的 DI 配置变得非常复杂,特别是因为我不得不处理我的测试运行程序并行运行我的测试,这意味着我必须注入线程安全的模拟和存根(恐怖!)。但即使没有并行运行测试,维护测试 DI 配置也是相当可怕的。

于 2012-01-13T12:19:44.443 回答