In a previous post, I showed how to make your step-definition code more maintainable in SpecFlow. If you migrate from SpecFlow/Reqnroll v2 to Reqnroll v3 then this post is for you!
TL;DR: Updated attribute for Reqnroll v3
Assuming you’re on .NET 8+ this class works for you. If you’re on an earlier version, just replace the collection expression with your preferred initializer.
public class GivenWhenAttribute : StepDefinitionBaseAttribute{ static readonly StepDefinitionType[] types = [ StepDefinitionType.Given, StepDefinitionType.When ]; public GivenWhenAttribute() : this(null!) { } public GivenWhenAttribute(string expression) : base(expression, types) { }}
Challenge: Culture no longer exists
The old SpecFlow-era overload set a Culture member via a constructor. In Reqnroll v3, that member is gone, so we remove this overload:
public GivenWhenAttribute(string regex, string culture) : this(regex) { Culture = culture; }
Challenge: step definition not discovered
After solving the Culture member, everything compiled fine, but binding discovery failed with this exception:
Message: Reqnroll.MissingStepDefinitionException : No matching step definition found for one or more steps.Stack Trace: ErrorProvider.ThrowPendingError(ScenarioExecutionStatus testStatus, String message)TestExecutionEngine.OnAfterLastStepAsync()TestRunner.CollectScenarioErrorsAsync()ReproductionFeature.ScenarioCleanupAsync()ReproductionFeature.CantFindStep() line 8...
Reqnroll discovers step definitions via reflection. It looks for methods having an attribute derived from StepDefinitionBaseAttribute
In V3 the parameter names of the constructors on your attribute must match Reqnroll’s expected names. If they don’t, Reqnroll does not recognize the attribute and discovery fails. Just changing the parameter name from regex to expression solves this problem.