CF7*_*CF7 9 c# integration-testing asp.net-core-hosted-services
我有 .NET Core Web API 项目,由于某些原因,我们在该项目中创建了一个后台服务,并在应用程序启动时开始运行后台服务。因此,我们创建了一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
为了在应用程序启动时运行它,我将后台服务添加到 Program.cs 中的托管服务中,如下所示:
.ConfigureServices(services =>
services.AddHostedService<BackgroundWorkerService>());
Run Code Online (Sandbox Code Playgroud)
现在,我们需要创建一个集成测试,并且我们希望在运行集成测试时停止后台服务。
有谁知道如何在集成测试中阻止它?我尝试从ConfigureTestServices 中删除该服务,但没有成功,集成测试开始时后台服务仍在运行。
Cam*_*ein 12
正如您在问题中提到的,您应该能够删除 中的服务ConfigureTestServices。然而,我们如何指定要删除的服务是这里的关键。
根据我的经验,您需要找到有问题的值ServiceDescriptor,而不是创建一个具有预期值的新值(请参阅下面的注释了解原因)。我使用 LINQ 和服务的实现BackgroundWorkerService类型(在您的情况下为)来轻松查找现有的ServiceDescriptor. 然后我可以将其从列表中删除,这意味着CreateClient()在WebApplicationFactory.
看起来像这样:
builder.ConfigureTestServices(services =>
{
var descriptor = services.Single(s => s.ImplementationType == typeof(BackgroundWorkerService));
services.Remove(descriptor);
}
Run Code Online (Sandbox Code Playgroud)
这种方法的一个非常好的好处是,它将测试逻辑保留在生产代码之外,并完全保留在测试的设置/夹具中。
关于IServiceCollection删除的注意事项:经过一番研究,我相信这是因为ServiceDescriptor除了 之外没有提供相等或比较方法Object.Equals,该方法回退到引用相等。因此,即使 new 中的所有值都相同ServiceDescriptor,它们也会是不同的对象,因此不会被发现并从服务列表中删除。
我找到了一个解决方案,将后台服务寄存器置于如下状态。
在注册后台服务部分编辑 Program.cs 文件,如下所示:
.ConfigureServices(services =>
{
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "INTEGRATION")
{
services.AddHostedService<BackgroundWorkerService>();
}
});
Run Code Online (Sandbox Code Playgroud)
然后尝试将变量从您需要的位置更改为 INTEGRATION。
| 归档时间: |
|
| 查看次数: |
4490 次 |
| 最近记录: |