【问题标题】:How is static object state shared/set between MSpec contexts?MSpec 上下文之间如何共享/设置静态对象状态?
【发布时间】:2013-02-14 00:32:13
【问题描述】:

在编写一些 MSpec BDD 测试时,我遇到了一个场景,即我预期会失败的测试通过了,但只有在我运行所有测试时才通过。当我单独运行测试时,它按预期失败了。经过一番调查,我发现在第二次测试运行之前,之前测试中设置的某些状态没有被重置,这导致第二次测试在我预期失败时通过。以下设计的代码重现了该场景:

public class ContextBase
{
    protected static object state;
}

public class Context_a : ContextBase
{
    Establish context = () => { state = new object(); };

    It should_set_state = () => state.ShouldNotBeNull();
}

public class Context_b : ContextBase
{
    Establish context = () => {  };

    It should_set_state = () => state.ShouldNotBeNull();
}

这两个测试都通过了,因为 Context_a 在 Context_b 之前执行,并且在执行 Context_B 时,在 Context_A 中设置的状态仍然设​​置。如果您单独运行 Context_B,则测试失败,因为尚未设置状态。有趣的是,如果您从 Context_B 中删除空的建立语句,那么 Context_B 将始终按预期失败。

我对 MSpec 比较陌生,这种行为让我很惊讶。我假设这样的状态会在执行每个上下文之间被重置。也许我错过了一些东西......我是否正确构建了这些测试?如果 MSpec 没有在上下文之间自动重置这样的状态,那么我应该使用什么策略来确保在我的示例中的情况下重置状态?我应该在将所有状态字段设置为 null 的 ContextBase 类上放置一个建立 lambda 吗?

【问题讨论】:

    标签: mspec


    【解决方案1】:

    MSpec 不会在执行上下文之间“重置”静态状态。它遵循您从普通静态变量中知道的行为,即除非您手动执行此操作,否则它们不会在应用程序(即测试运行)运行时重新初始化。最好初始化每个上下文的Establish中的所有字段。

    另一种选择是在您的基类上添加一个额外的Establish,但这会在您的上下文中隐藏重要信息 - 您必须导航到基类才能看到某个字段已使用特定值初始化。但 DRY 通常不适用于测试:我更喜欢使用从派生上下文调用的带有 protected static 方法的基类(例如,请参阅 this answer)。

    【讨论】:

    • 感谢您的回答。我注意到在您链接到的示例中,您还重复了每个上下文中的静态变量,而不是将它们放在基类中,我想这本身也解决了我遇到的问题。当系统设计发生变化时,您是否发现在每个上下文中重复这样的代码会使重构测试变得复杂?您提到 DRY 通常不适用于测试,但我总是被教导(可能是错误的)我应该像对待任何其他代码一样注意保持测试 DRY。再次感谢您的回答!
    • 嗨,约翰。为了详细说明 Alexander 对 DRY 的评论,可执行规范旨在对给定的与系统的交互进行建模。排除辅助设置细节很好,但排除与理解给定交互相关的协作会导致模糊测试。如需进一步阅读,请参阅:lostechies.com/derekgreer/2011/07/19/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多