dotnet / dotnet/aspnetcore

The Host initiated by WebApplicationFactory fails to terminate

Open
#61,372 2 comments 0 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

## Bug
The Host initiated by WebApplicationFactory fails to terminate.

## Reproduce:

### [Program.cs](https://github.com/t03apt/AppLifecycleTroubleshooting/blob/5f97b95396b819ba0a346ee147839a808729d584/WebApi/Program.cs)
```csharp

namespace WebApi;

public partial class Program
{
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup();
})
.ConfigureServices(services =>
{
services.Configure(options =>
{
options.ShutdownTimeout = TimeSpan.FromSeconds(1);
});
});
}

public class Startup
{
public static void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); });
}

public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
services.AddHostedService();
}
}

public class MyBackgroundService(ILogger logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Yield();

try
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogInformation("My background service is running.");
await Task.Delay(1000, stoppingToken);

throw new InvalidOperationException();
}
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
// ignore
}
}
}
```

### [UnitTest1.cs](https://github.com/t03apt/AppLifecycleTroubleshooting/blob/5f97b95396b819ba0a346ee147839a808729d584/WebApiTests/UnitTest1.cs)
```csharp
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApiTests
{
public class UnitTest1 : IClassFixture>
{
private readonly WebApplicationFactory _factory;

public UnitTest1(WebApplicationFactory factory)
{
_factory = factory;
}

[Fact]
public async Task ApplicationShouldShutdownGracefullyOnFailingHostedService()
{
// Arrange
var lifetime = _factory.Services.GetRequiredService();

// Act
await Task.Delay(TimeSpan.FromSeconds(5));

// Assert
Assert.True(lifetime.ApplicationStopping.IsCancellationRequested, "Expected lifetime.ApplicationStopping.IsCancellationRequested to be true");
Assert.True(lifetime.ApplicationStopped.IsCancellationRequested, "Expected lifetime.ApplicationStopped.IsCancellationRequested to be true");
}
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.