-
Notifications
You must be signed in to change notification settings - Fork 114
Description
Reqnroll Version
Reqnroll.NUNit (2.3.0) + Reqnroll.Microsoft.Extensions.DependencyInjection (2.3.0)
Which test runner are you using?
NUnit
Test Runner Version Number
NUnit3TestAdapter 5.0.0
.NET Implementation
.NET 8.0
Test Execution Method
ReSharper Test Runner
Content of reqnroll.json configuration file
{
"language": {
"feature": "en-US"
}
}Issue Description
Problem
In my tests, I have DI setup:
services.AddScoped<IDbStorage, DbStorage>();By default, the DI container disposes all classes when the scope is closed or the test suite ends (in the case of singleton registration).
My DbStorage class uses a third-party library that has an async disposal API only, DisposeAsync, implemented through the IAsyncDisposable interface. So, if I make my DbStorage implement IAsyncDisposable, I will get an exception during teardown:
TearDown : System.InvalidOperationException : 'DbStorage' type only implements IAsyncDisposable. Use DisposeAsync to dispose the container.
--TearDown
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose()
at Reqnroll.Microsoft.Extensions.DependencyInjection.DependencyInjectionPlugin.AfterScenarioPluginLifecycleEventHandler(Object sender, RuntimePluginAfterScenarioEventArgs eventArgs)
at Reqnroll.Plugins.RuntimePluginTestExecutionLifecycleEvents.RaiseAfterScenario(IObjectContainer objectContainer)
at Reqnroll.Plugins.RuntimePluginTestExecutionLifecycleEventEmitter.RaiseExecutionLifecycleEvent(HookType hookType, IObjectContainer container)
at Reqnroll.Infrastructure.TestExecutionEngine.FireRuntimePluginTestExecutionLifecycleEvents(HookType hookType)
at Reqnroll.Infrastructure.TestExecutionEngine.FireEventsAsync(HookType hookType)
at Reqnroll.Infrastructure.TestExecutionEngine.FireScenarioEventsAsync(HookType bindingEvent)
at Reqnroll.Infrastructure.TestExecutionEngine.OnScenarioEndAsync()
at Reqnroll.TestRunner.OnScenarioEndAsync()
at Tests.Feature.TestTearDownAsync()
at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.GetResult()
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await[TResult](TestExecutionContext context, Func`1 invoke)
at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(TestExecutionContext context, Func`1 invoke)
at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunSetUpOrTearDownMethod(TestExecutionContext context, IMethodInfo method)
at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunTearDown(TestExecutionContext context)
As a workaround I need to implement IDisposable in DbStorage and call the async api from the synchronous Dispose method which is considered bad practice because it blocks the thread and consumes thread resources:
public class DbStorage : IDbStorage, IDisposable
{
public void Dispose()
{
ThirdPartyLibraryDisposeAsync().GetAwaiter().GetResult();
}
}
I want to make my DbStorage class only implement IAsyncDisposable to remove the sync -> async call and free up thread pool resources in CI runners.
Steps to Reproduce
- Register
Scopedlifetime dependency that implementsIAsyncDisposableinterface usingReqnroll.Microsoft.Extensions.DependencyInjectionplugin - Launch test using this dependency
- Got
System.InvalidOperationExceptionerror during teardown.
Link to Repro Project
No response