Using RunOaktonCommands in combination with a test using a WebApplicationFactory results in a ObjectDisposedException
I have the following program: public sealed class Program { public static async Task Main(params string[] args) { try { var builder = WebApplication.CreateBuilder(args); await using var app = builder .Build(); app.UseRequestLocalization( new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("nl-NL"), }); await app.RunOaktonCommands(args); } catch (Exception e) { Console.WriteLine(e); throw; } } } With the following Test: public class Tests : WebApplicationFactory { protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment("UnitTest"); builder.ConfigureLogging(l => l.AddConsole()); } [Test] public async Task Test1() { Server.PreserveExecutionContext = true; using var client = CreateClient(); Assert.Pass(); } } This results in a failed test with the following error log: Test1 Source: UnitTest1.cs line 17 Duration: 279 ms Message: System.ObjectDisposedException : Cannot access a disposed object. Object name: 'IServiceProvider'. Stack Trace: ThrowHelper.ThrowObjectDisposedException() ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope) ServiceProvider.GetService(Type serviceType) ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) WebApplicationFactory`1.ConfigureHostBuilder(IHostBuilder hostBuilder) WebApplicationFactory`1.EnsureServer() WebApplicationFactory`1.get_Server() Tests.Test1() line 23 GenericAdapter`1.GetResult() AsyncToSyncAdapter.Await(Func`1 invoke) TestMethodCommand.RunTestMethod(TestExecutionContext context) TestMethodCommand.Execute(TestExecutionContext context) c__DisplayClass1_0.b__0() DelegatingTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Standard Output: [red]Invalid usage[/][yellow]Unknown argument or flag for value --environment=UnitTest[/] run - Start and run this .Net application └── Start and run this .Net application └── dotnet run -- run ├── [-c, --check] ├── [-e, --environment ] ├── [-v, --verbose] ├── [-l, --log-level │ Trace|Debug|Information|Warning|Error|Critical|None] └── [--config: ] Usage Description ──────────────────────────────────────────────────────────────────────────────── [-c, --check] Run the environment checks before starting the host [-e, --environment ] Use to override the ASP.Net Environment name [-v, --verbose] Write out much more information at startup and enables console logging [-l, --log-level Override the log level Trace|Debug|Information|Warning|Error |Critical|None] [--config: ] Overwrite individual configuration items If I change "app.RunOaktonCommands(args)" into "app.RunAsync()" the unit test succeeds. So something in RunOaktonCommands is either requesting a disposed object or disposing an object prematurely. Am I missing something, am I doing some configuration wrong, is the cause of this issue the warning by Oakton, or is this something out of my control?
I have the following program:
public sealed class Program
{
public static async Task Main(params string[] args)
{
try
{
var builder = WebApplication.CreateBuilder(args);
await using var app = builder
.Build();
app.UseRequestLocalization(
new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("nl-NL"),
});
await app.RunOaktonCommands(args);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
With the following Test:
public class Tests : WebApplicationFactory
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("UnitTest");
builder.ConfigureLogging(l => l.AddConsole());
}
[Test]
public async Task Test1()
{
Server.PreserveExecutionContext = true;
using var client = CreateClient();
Assert.Pass();
}
}
This results in a failed test with the following error log:
Test1
Source: UnitTest1.cs line 17
Duration: 279 ms
Message:
System.ObjectDisposedException : Cannot access a disposed object.
Object name: 'IServiceProvider'.
Stack Trace:
ThrowHelper.ThrowObjectDisposedException()
ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
ServiceProvider.GetService(Type serviceType)
ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
WebApplicationFactory`1.ConfigureHostBuilder(IHostBuilder hostBuilder)
WebApplicationFactory`1.EnsureServer()
WebApplicationFactory`1.get_Server()
Tests.Test1() line 23
GenericAdapter`1.GetResult()
AsyncToSyncAdapter.Await(Func`1 invoke)
TestMethodCommand.RunTestMethod(TestExecutionContext context)
TestMethodCommand.Execute(TestExecutionContext context)
<>c__DisplayClass1_0.b__0()
DelegatingTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
Standard Output:
[red]Invalid usage[/][yellow]Unknown argument or flag for value --environment=UnitTest[/]
run - Start and run this .Net application
└── Start and run this .Net application
└── dotnet run -- run
├── [-c, --check]
├── [-e, --environment ]
├── [-v, --verbose]
├── [-l, --log-level
│ Trace|Debug|Information|Warning|Error|Critical|None]
└── [--config: ]
Usage Description
────────────────────────────────────────────────────────────────────────────────
[-c, --check] Run the environment checks before
starting the host
[-e, --environment ] Use to override the ASP.Net
Environment name
[-v, --verbose] Write out much more information at
startup and enables console logging
[-l, --log-level Override the log level
Trace|Debug|Information|Warning|Error
|Critical|None]
[--config: ] Overwrite individual configuration
items
If I change "app.RunOaktonCommands(args)" into "app.RunAsync()" the unit test succeeds. So something in RunOaktonCommands is either requesting a disposed object or disposing an object prematurely.
Am I missing something, am I doing some configuration wrong, is the cause of this issue the warning by Oakton, or is this something out of my control?