ScenarioContext and FeatureContext in SpecFlow 3.0 and Later

With SpecFlow 3.0, we marked ScenarioContext.Current and FeatureContext.Current as obsolete, to make clear that you that you should avoid using these properties in future. The reason for moving away from these properties is that they do not work when running scenarios in parallel.

So how do you now access ScenarioContext and FeatureContext?

Let’s first focus on ScenarioContext. Previously you would access ScenarioContext using code similar to this:

[Binding]
public class Bindings
{
    [Given(@"I have entered (.*) into the calculator")]
    public void GivenIHaveEnteredIntoTheCalculator(int number)
    {
        ScenarioContext.Current["Number1"] = number;
    }

    [BeforeScenario()]
    public void BeforeScenario()
    {
        Console.WriteLine("Starting " + ScenarioContext.Current.ScenarioInfo.Title);
    }
}

As of SpecFlow 3.0, you now need to use context injection to acquire an instance of ScenarioContext by requesting it via the constructor.

public class Bindings
{
    private readonly ScenarioContext _scenarioContext;

    public Bindings(ScenarioContext scenarioContext)
    {
        _scenarioContext = scenarioContext;
    }
}

Once you have acquired the instance of ScenarioContext, you can use it with the same methods and properties as before.

So our example will now look like this:

public class Bindings
{
    private readonly ScenarioContext _scenarioContext;

    public Bindings(ScenarioContext scenarioContext)
    {
        _scenarioContext = scenarioContext;
    }

    [Given(@"I have entered (.*) into the calculator")]
    public void GivenIHaveEnteredIntoTheCalculator(int number)
    {
        _scenarioContext["Number1"] = number;
    }

    [BeforeScenario()]
    public void BeforeScenario()
    {
        Console.WriteLine("Starting " + _scenarioContext.ScenarioInfo.Title);
    }
}

But what about FeatureContext?

In normal bindings as well as Before/After Scenario, Before/After ScenarioBlock and Before/After Step hooks, you can acquire the FeatureContext in the same way as ScenarioContext. However, if you want to use it together with Before/After Feature hooks, you need to acquire it via a function parameter.

Previously:

public class Hooks
{
    [AfterFeature()]
    public static void AfterFeature()
    {
        Console.WriteLine("Finished " + FeatureContext.Current.FeatureInfo.Title);
    }
}

Now:

public class Hooks
{
    [AfterFeature]
    public static void AfterFeature(FeatureContext featureContext)
    {
        Console.WriteLine("Finished " + featureContext.FeatureInfo.Title);
    }
}

Conclusion

The number of steps required to deal with these obsolete warnings is minimal, unlike some cases, where a lot of refactoring is needed. You can find working examples in our example collection, one example from before refactoring and one after refactoring.

We have also made a short video to demonstrate the process and show how little there is to it:

ADD VIDEO LINK