托管服务集成测试.Net-Core`

joh*_*y 5 11 c# mstest .net-core asp.net-core asp.net-core-hosted-services

我有一个QueueTask托管服务(.Net-Core的新后台服务),我想测试.我的queuedHosted服务看起来像这样:

public QueuedHostedService(IServiceProvider serviceProvider, IBackgroundTaskQueue taskQueue, ILoggerFactory loggerFactory)
{
    TaskQueue = taskQueue;
    _logger = loggerFactory.CreateLogger<QueuedHostedService>();
    _serviceProvider = serviceProvider;
}

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
    using (var scope = _serviceProvider.CreateScope())
    {
        while (false == stoppingToken.IsCancellationRequested)
        {
            var workItem = await TaskQueue.DequeueAsync(stoppingToken);
            try
            {
                await workItem(scope.ServiceProvider, stoppingToken);
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, $"Error occurred executing {nameof(workItem)}.");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它只是从队列中读取任务并在它们进入时执行它们.我已经验证了托管服务正在生产中.我为它写了一个测试:

[TestMethod]
public async Task Verify_Hosted_Service_Executes_Task()
{
    IServiceCollection services = new ServiceCollection();
    services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
    services.AddHostedService<QueuedHostedService>();
    services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
    var serviceProvider = services.BuildServiceProvider();

    var backgroundQueue = serviceProvider.GetService<IBackgroundTaskQueue>();

    var isExecuted = false;
    backgroundQueue.QueueBackgroundWorkItem(async (sp, ct) => {
        isExecuted = true;
    });

    await Task.Delay(10000);
    Assert.IsTrue(isExecuted);
}
Run Code Online (Sandbox Code Playgroud)

但是,我的回电从未被击中过.如何让我的任务在后台服务上执行?

编辑

我正在模仿创业公司,并假设后台服务会起作用,但显然我的服务从未开始,

托管服务是如何从.Net-Core开始标准化的?

Nko*_*osi 13

托管服务由框架启动,作为WebHost启动过程的一部分

// Fire IHostedService.Start
await _hostedServiceExecutor.StartAsync(cancellationToken).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

资源

通过HostedServiceExecutor这将收集所有已注册的集合IHostedService,枚举它们并依次启动它们

public HostedServiceExecutor(ILogger<HostedServiceExecutor> logger, IEnumerable<IHostedService> services)
{
    _logger = logger;
    _services = services;
}

public async Task StartAsync(CancellationToken token)
{
    try
    {
        await ExecuteAsync(service => service.StartAsync(token));
    }
    catch (Exception ex)
    {
        _logger.ApplicationError(LoggerEventIds.HostedServiceStartException, "An error occurred starting the application", ex);
    }
}
Run Code Online (Sandbox Code Playgroud)

资源

但是,由于您自己测试托管服务,因此您必须充当框架并自行启动服务.

[TestMethod]
public async Task Verify_Hosted_Service_Executes_Task() {
    IServiceCollection services = new ServiceCollection();
    services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
    services.AddHostedService<QueuedHostedService>();
    services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
    var serviceProvider = services.BuildServiceProvider();

    var service = serviceProvider.GetService<IHostedService>() as QueuedHostedService;

    var backgroundQueue = serviceProvider.GetService<IBackgroundTaskQueue>();

    await service.StartAsync(CancellationToken.None);

    var isExecuted = false;
    backgroundQueue.QueueBackgroundWorkItem(async (sp, ct) => {
        isExecuted = true;
    });

    await Task.Delay(10000);
    Assert.IsTrue(isExecuted);

    await service.StopAsync(CancellationToken.None);
}
Run Code Online (Sandbox Code Playgroud)

  • 您还可以使用以下方式获取新服务(特别是如果您注册了多个 IHostedInstaces) serviceProvider.GetServices&lt;IHostedService&gt;().OfType&lt;YourType&gt;().Single(); (2认同)