簡體   English   中英

.NET Core 中的托管服務單元測試

[英]Unit testing Hosted Services in .NET Core

我有一個后台任務由 .NET Core 中的托管服務實現。 這個 class 的邏輯很少:

public class IndexingService : IHostedService, IDisposable
{
    private readonly int indexingFrequency;

    private readonly IIndexService indexService;

    private readonly ILogger logger;

    private bool isRunning;

    private Timer timer;

    public IndexingService(ILogger<IndexingService> logger, IIndexService indexService, IndexingSettings indexingSettings)
    {
        this.logger = logger;
        this.indexService = indexService;

        this.indexingFrequency = indexingSettings.IndexingFrequency;
    }

    public void Dispose()
    {
        this.timer?.Dispose();
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        this.timer = new Timer(this.DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(this.indexingFrequency));
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        this.timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        if (this.isRunning)
        {
            // Log
            return;
        }

        try
        {
            this.isRunning = true;
            this.indexService.IndexAll();
        }
        catch (Exception e)
        {
            // Log, The background task should never throw.
        }
        finally
        {
            this.isRunning = false;
        }
    }
}

我的Startup看起來像:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHostedService<IndexingService>();
    services.AddTransient<IIndexService, IndexService>();
    // 'IndexingSettings' is read from appsetting and registered as singleton
}

如何對DoWork方法中的邏輯進行單元測試? 問題是托管服務是由框架管理的,不知道如何隔離這個class。

不知道關於隔離類的意思。 這些不是魔術。 ASP.NET核心只是實例化類的任何需要的依賴,然后調用StartAsync ,后來StopAsync上的應用程序停機。 沒有什么是您無法手動完成的。

換句話說,要對其進行單元測試,您可以模擬依賴項,實例化該類,然后對其調用StartAsync 但是,我認為總體托管服務更適合集成測試。 您可以將任何實際的工作分解為一個幫助程序類,該類對於單元測試而言將更為簡單,然后只需在服務上運行集成測試以確保其通常能夠完成預期的工作即可。

使用以下命令從依賴注入容器中檢索托管服務:

. . .
services.AddHostedService<IndexingService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
IndexingService indexingService = serviceProvider.GetService<IHostedService>() as IndexingService;
. . .

我有一個BackgroundService的子 class 我想對其進行單元測試。 這個 MS 測試運行良好!

[TestMethod()]
public async Task ExecuteAsync_TaskQueue()
{
    // Arrange
    var cancellationToken = new CancellationToken();
    await _sut.StartAsync(cancellationToken);

    // Act
    _sut.TaskQueue.QueueBackgroundWorkItem(DoSomething);
    await _sut.StopAsync(cancellationToken);

    // Assert
    Assert.AreEqual(_codeExecuted, true);
}

public Task DoSomething(CancellationToken cancellationToken)
{
    _codeExecuted = true;
    return Task.CompletedTask;
}

這與它在運行時的工作方式非常相似。 ASP.NET 框架將調用StartAsync 然后在您的應用程序生命周期的某個時刻,將執行后台作業(在我的情況下QueueBackgroundWorkItem )。 您可以在DoSomething中放置一個斷點,然后查看它是否實際被調用。

通過這種方式,您可以只對 BackgroundService 進行單元測試,而無需測試任何其他應用程序邏輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM