I have a simple health check test which looks like this:
public class HealthCheckEndpointTests : IClassFixture<ItemsApplicationFactory>
{
private readonly ItemsApplicationFactory _factory;
public HealthCheckEndpointTests(ItemsApplicationFactory factory)
{
_factory = factory;
}
public async Task HealthCheck_Test()
{
// Arrange
HttpClient httpClient = _factory.CreateClient();
// Act
string response = await httpClient.GetStringAsync("/health/live");
// Assert
Assert.Equal("Healthy", response);
}
}
My ItemsApplicationFactory looks like this:
public class ItemsApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureKestrel(options => options.AllowSynchronousIO = true);
builder.ConfigureServices(services =>
{
// remove db context options if exists
var dbContextDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<ItemsDbContext>));
if (dbContextDescriptor != null)
services.Remove(dbContextDescriptor);
var serviceCollection = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
services.AddDbContext<ItemsDbContext>(mariaDb =>
{
mariaDb.UseInMemoryDatabase("template");
mariaDb.UseInternalServiceProvider(serviceCollection);
});
});
}
}
When I run the test, I get the following exception thrown
System.ObjectDisposedException : Cannot access a disposed object.
Object name: 'IServiceProvider'
I have changed my test, to see if the exception is caused by initialization of ItemsApplicationFactory or HttpClient. So the test looks like this
public class HealthCheckEndpointTests : IClassFixture<ItemsApplicationFactory>
{
private readonly ItemsApplicationFactory _factory;
public HealthCheckEndpointTests(ItemsApplicationFactory factory)
{
_factory = factory;
}
public async Task HealthCheck_Test()
{
// Arrange
HttpClient httpClient = _factory.CreateClient();
// Act
await Task.Run(() => Task.CompletedTask);
// Assert
Assert.True(true);
}
}
The test did not throw any exception.
Why _factory.CreateClient();
does not throw, but httpClient.GetStringAsync("/health/live")
does? And how to fix that?
I was experiencing the same. One possible reason is that something fails in the test execution but you are failing to find out what exactly, and the test shows that IServiceProvider
was disposed.
That's not the cause, but the consequence.
Go to your Program.cs
and wrap everything under a
try {
//...
} catch(Exception exception) {
// breakpoint here to find out the real reason
throw; // do not forget to also throw the same exception
}
and debug the test. You'll see the real reason causing the error you're seeing.
Careful not to swallow the exception. I'd log fatal error and throw;
, but this is just for the purpose of finding out while debugging what's the real reason causing the problem.
In my case it was one driver trying to connect to CosmosDb when the SSL was not trusted, but it could be anything.