.NET Core 在集成测试中停止 HostedService

.NET Core stop HostedService in the Integration test

我有 .NET Core web API 项目,由于某些原因,我们在这个项目中创建了一个后台服务,并在应用程序启动时启动 运行ning 后台服务。 因此,我们创建了一个 BackgroundWorkderService,它继承自 BackgroundService (Microsoft.Extensions.Hosting),如下所示:

public class BackgroundWorkerService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await DoWork(stoppingToken);
    }

    public override async Task StartAsync(CancellationToken cancellationToken)
    {
        await ExecuteAsync(cancellationToken);
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

为了 运行 它在应用程序启动时,我将后台服务添加到 Program.cs 中的托管服务,如下所示:

.ConfigureServices(services =>
                services.AddHostedService<BackgroundWorkerService>());

现在,我们需要创建一个集成测试,我们想在 运行 集成测试时停止后台服务。

有谁知道如何在集成测试中停止它?我试图从 ConfigureTestServices 中删除该服务,但没有成功,当集成测试开始时,后台服务仍然 运行s。

我找到了一个解决方案,可以将后台服务寄存器设置为如下状态。

在注册后台服务部分编辑 Program.cs 文件:

.ConfigureServices(services =>
        {
            if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "INTEGRATION")
            {
                services.AddHostedService<BackgroundWorkerService>();
            }
        });

然后尝试根据需要将变量更改为 INTEGRATION。

正如您在问题中提到的那样,您应该能够删除 ConfigureTestServices 中的服务。然而,我们究竟如何指定要删除的服务是这里的关键。

根据我的经验,您需要 找到 有问题的 ServiceDescriptor 而不是创建一个具有预期值的新值(请参阅下面的注释了解原因)。我使用 LINQ 和服务的 实现 类型(在您的例子中,BackgroundWorkerService)轻松找到现有的 ServiceDescriptor。然后我可以将它从列表中删除,这意味着它不会在 WebApplicationFactory.

上调用 CreateClient() 时启动

看起来像这样:

builder.ConfigureTestServices(services =>
{
    var descriptor = services.Single(s => s.ImplementationType == typeof(BackgroundWorkerService));
    services.Remove(descriptor);
}

这种方法的一个非常好的好处是它将测试逻辑排除在生产代码之外,并且完全在 setup/fixture 中用于测试。

关于 IServiceCollection 删除的注意事项:经过一番探究,我相信这是因为 ServiceDescriptor doesn't provide an equality or comparison method other than Object.Equals,这又回到了引用相等性。因此,即使新 ServiceDescriptor 中的所有值都相同,它们也会是不同的对象,因此不会被发现并从服务列表中删除。