SpecFlow icon indicating copy to clipboard operation
SpecFlow copied to clipboard

IAsyncLifetime not respected on Step definitions class, how should I call async disposal on injected context

Open elijahmondero opened this issue 1 year ago • 3 comments

SpecFlow Version

3.9

Which test runner are you using?

xUnit

Test Runner Version Number

2.4.5

.NET Implementation

.NET 6.0

Project Format of the SpecFlow project

Sdk-style project format

.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

N/A

Issue Description

I wish to inject a context in the [Given] step. However the documentation says that injected context are disposed if they implement IDisposable. However the contexts I need to inject need to be disposed asynchronously. When I use xunit directly (prior to using specflow) I was able to implement IAsynchLifetime and call await myInjectedContextObject.DisposeAsync().

Could you tell me what the specflow way of doing this is please?

Steps to Reproduce

Add IAsyncLifetime to any steps definition class. The async Task InitialiseAsynch() and async Task DisposeAsymch() are not called when running the feature

Link to Repro Project

No response

elijahmondero avatar May 02 '23 03:05 elijahmondero

My current workaround are hooks + parameter injection:

[Binding]
public class GateKeepingTests
{
    private readonly ExpensiveFixture _fixture;

    public GateKeepingTests(ExpensiveFixture fixture)
    {
        _fixture = fixture;
    }

    [BeforeFeature]
    public static async Task Before(ExpensiveFixture fixture)
    {
        await fixture.InitializeAsync();
    }

    [AfterFeature]
    public static async Task After(ExpensiveFixture fixture)
    {
        await fixture.DisposeAsync();
    }
}

jernejg avatar Jun 18 '23 01:06 jernejg

My current workaround are hooks + parameter injection:

[Binding]
public class GateKeepingTests
{
    private readonly ExpensiveFixture _fixture;

    public GateKeepingTests(ExpensiveFixture fixture)
    {
        _fixture = fixture;
    }

    [BeforeFeature]
    public static async Task Before(ExpensiveFixture fixture)
    {
        await fixture.InitializeAsync();
    }

    [AfterFeature]
    public static async Task After(ExpensiveFixture fixture)
    {
        await fixture.DisposeAsync();
    }
}

I had to do the same thing here.

marcelloguimaraes avatar Apr 08 '24 18:04 marcelloguimaraes

Hello @jernejg , Do these async Hooks work when running tests in parallel? I have something like this: `[Binding] public class BeforeFeatureHooks {

public BeforeFeatureHooks(FeatureContext featureContext)
{
    _featureContext = featureContext;
}
[BeforeFeature]
public static async Task SomeBeforeFeatureHook(FeatureContext featureContext, TestDataGenerator testDataGenerator)
{
   var someTestData = await testDataGenerator.Generate();
   featureContext.Add("some key", someTestData);
}`

and then, in my steps definitions, where I user DI and passing FeatureContext featureContext in the Steps definitions constructors and trying go get the key from the featureContext - for part of the tests this key is unavailable.

victorBychinski avatar May 20 '24 03:05 victorBychinski