SpecFlow.NUnit tests do not work when LifeCycle.InstancePerTestCase is configured on assembly-level
SpecFlow Version
3.9.8
Which test runner are you using?
NUnit
Test Runner Version Number
4.0.0
.NET Implementation
equal or greater .NET Framework 4.6.1
Project Format of the SpecFlow project
Classic project format using <PackageReference> tags
.feature.cs files are generated using
SpecFlow.Tools.MsBuild.Generation NuGet package
Test Execution Method
Visual Studio Test Explorer
SpecFlow Section in app.config or content of specflow.json
Issue Description
NUnit 3.13 introduced FixtureLifeCycle.
Configuring "instance per test" as default for the whole assembly/project can be done via [assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)] attribute.
Unfortunately, the generated tests by the SpecFlow.NUnit are not compatible with this, because it requires NUnit's OneTimeSetup and OneTimeTeardown to be static.
This scenario might sound a bit strange, but our team actually faces this. We have a test project that is configured to use LifeCycle.InstancePerTestCase in the whole project as described. Our tests are not using SpecFlow so far, but we slowly want to migrate to SpecFlow for those test cases.
Our current workaround is to apply the LifeCycle.InstancePerTestCase attribute to all non-SpecFlow NUnit tests.
Steps to Reproduce
Steps
- create a new .NET Framework project (target framework version does not matter, I used .NET 4.8)
- reference nuget packages SpecFlow.Nunit.Runners (or install latest versions of this dependency package manually)
- create a dummy feature file with an empty scenario (no Given/When/Then steps required)
- add attribute
[assembly: NUnit.Framework.FixtureLifeCycle(NUnit.Framework.LifeCycle.InstancePerTestCase)](e.g. to AssemblyInfo.cs) - build the project
- run the tests with the Visual Studio test runner
Expected: test succeeds Actual: test fails with error message
OneTimeSetUp: System.InvalidOperationException : Only static OneTimeSetUp and OneTimeTearDown are allowed for InstancePerTestCase mode.
Link to Repro Project
No response
another workaround we came up with is a custom MSBuild target to set the FixtureLifeCycle attribute after SpecFlow generated the source files, like this:
<!-- workaround for https://github.com/SpecFlowOSS/SpecFlow/issues/2466 -->
<Target Name="SpecflowAdjustFixtureLifeCycle" BeforeTargets="CoreCompile" AfterTargets="GenerateFeatureFileCodeBehindTask">
<WriteLinesToFile
File="%(SpecFlowGeneratedFiles.Identity)"
Lines="$([System.IO.File]::ReadAllText(%(SpecFlowGeneratedFiles.Identity)).Replace('TestFixtureAttribute()','TestFixtureAttribute(), NUnit.Framework.FixtureLifeCycle(NUnit.Framework.LifeCycle.SingleInstance)'))"
Overwrite="true"
Encoding="Unicode"/>
</Target>