【问题标题】:IOC (simpleServiceLocator) setup testing with Specflow and WatiN使用 Specflow 和 WatiN 进行 IOC(simpleServiceLocator)设置测试
【发布时间】:2012-01-13 04:06:26
【问题描述】:

我使用 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 ...

【问题讨论】:

    标签: inversion-of-control ioc-container watin specflow service-locator


    【解决方案1】:

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

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

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

    【讨论】:

    • Steven,感谢您的建议...我无法使用构造函数注入,因为我正在使用无法(轻松)更新的遗留代码。当我在测试项目中从具有属性 AssemblyInitialize 的方法调用 SetLocatorProvider 时,ServiceLocator.Current 在我正在测试的项目中为空,大概是因为它是一个单独的过程,但不确定如果我不能使用构造函数注入该怎么办.. .
    • 确保调用了用 [AssemblyInitialize] 修饰的方法。它应该有效,我过去就是这样做的。您可能需要查看此类方法的签名应该是什么以及将其准确放置在哪里(例如,在用 [TestClass] 属性装饰的类中)。
    • 这本书可能对您和您的项目感兴趣:Working Effectively with Legacy Code
    猜你喜欢
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    相关资源
    最近更新 更多