How is static object state shared / set between MSpec contexts?

While writing MSpec BDD tests, I ran into a scenario where the test I expected to get passed, but only when I ran all my tests. When I ran the test individually, it failed as expected. After some research, I found that some state that was set in the previous test was not reset until the second test was done and this caused the second test to pass when I expected it to fail ... The following contrived code reproduces the scenario:

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();
}

      

Both of these tests pass because Context_a runs before Context_b, and at the time Context_B is running, the state that was set to Context_A is still set. If you run Context_B in isolation then the test fails because the state is not set. Interestingly, if you remove the empty Set statement from Context_B, Context_B will always fail as expected.

I am relatively new to MSpec and this behavior surprised me. I assumed such a state would be reset between the execution of each context. I may have missed something ... Am I building these tests correctly? If MSpec doesn't support reset in this way automatically between contexts, what strategy should I use to ensure that the state is reset in cases like my example? Should I put a New label in the ContextBase class that sets all state fields to zero?

+3


source to share


1 answer


MSpec does not perform a static "reset" state between executable contexts. It obeys the behavior you know from normal static variables i.e. They do not get reinitialized while the application is running (i.e. Test Run) unless you do it manually. Your best bet is to initialize all fields in Establish

each context.



Another option is to add an extra one Establish

to your base class, but this will hide important information from your context - you will have to go to the base class to see that the field has been initialized to a specific value. But DRY is not about testing at all: I prefer to have base classes with methods protected static

that I call from derived contexts (see this answer for an example).

+2


source







All Articles