在 .net 核心 Ihostedservice 上编写单元测试的好做法是什么?

ris*_*shi 5 unit-testing background-process microservices asp.net-core-hosted-services

我有一个在 .net core 2.0 启动时启动的后台任务,从 backgroundservice 继承,实现了 StartAsync、StopAsync 和 ExecuteAsync。这个任务是根据一些业务逻辑定期更新数据库表中的一些数据。

虽然我可以将后台任务作为应用程序运行并使用日志、数据库检查和其他工具的帮助进行测试,但单元测试是否是测试后台任务所必需的?如果是这样,如何将任务注册为具有依赖项的服务并触发 start 和 stop 方法来断言实际与预期?欣赏一些基本的示例单元测试方法,用于测试基于 .net 核心 ihostedservice 后台任务的计时器。

这是我的基本测试开始,仅用于示例,但尚未完成。话虽如此,这只是一个想法,而不是确切的工作测试。这是需要社区帮助的地方。还可以添加更多断言,即 Assert.Verify()?

  [Fact]
        public async void Run_background_task_success()
        {
            //Arrange
            IServiceCollection services = new ServiceCollection();

            services.AddHostedService<BackgroundManagerTask>();

            var serviceProvider = services.BuildServiceProvider();

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

            var isExecuted = false;
            if(await service.StartAsync(CancellationToken.None))
{
isExecuted = true;
}

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

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

Jim*_*mex 0

我通常是这样做的。您提到您要访问数据库来更新一些数据,所以我假设您希望将其作为依赖项BackgroundManager

[Fact]
public void BackgroundManagerUpdatingDataTest()
{
    // Arrange
    Mock<IDataAccess> dbMock = new Mock<IDataAccess>();
    dbMock.Setup(x => x.UpdateSomethingInDB(It.IsAny<BusinessObject>())).Returns(1); // One row updated from the DML in UpdateSomethingInDB from the BusinessObject
    
    BackgroundManager sut = new BackgroundManager(dbMock.Object); // System under test.

    // Act
    await sut.StartAsync(CancellationToken.None);
    await Task.Delay(500); // Give the test some time to execute.
    await sut.StopAsync(CancellationToken.None); // Stop the Background Service.

    // Assert
    dbMock.Verify(x => x.UpdateSomethingInDB(It.IsAny<BusinessObject>()), Times.Exactly(1));
}
Run Code Online (Sandbox Code Playgroud)

上面,我们通过模拟数据访问调用并验证它是否被调用一次来简单地测试数据库的更新。

当然,您可以使用Moq模拟任何其他依赖项,并在您想要验证的任何其他内容上断言。