Unit testing 在.net核心Ihostedservice上编写单元测试的良好实践是什么?

Unit testing 在.net核心Ihostedservice上编写单元测试的良好实践是什么?,unit-testing,microservices,background-process,asp.net-core-hosted-services,Unit Testing,Microservices,Background Process,Asp.net Core Hosted Services,我有一个在.NETCore2.0启动时启动的后台任务,从backgroundservice继承,实现StartAsync、StopAsync和ExecuteAsync。这个任务是根据一些业务逻辑定期更新数据库表中的一些数据 虽然我可以将backgroundtask作为一个应用程序运行,并使用logs、db check和其他工具进行测试,但测试backgroundtask是否需要单元测试?如果是这样,如何将任务注册为具有依赖关系的服务,并触发start和stop方法来断言实际的vs预期值?欣赏一些

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

虽然我可以将backgroundtask作为一个应用程序运行,并使用logs、db check和其他工具进行测试,但测试backgroundtask是否需要单元测试?如果是这样,如何将任务注册为具有依赖关系的服务,并触发start和stop方法来断言实际的vs预期值?欣赏一些测试基于计时器的.net内核ihostedservice后台任务的基本样本单元测试方法

这里是我的基本测试开始只是为了样本,但还没有完成。话虽如此,这只是一个想法,而不是确切的工作测试。以下是需要社区帮助的内容。还可以添加更多断言,例如Assert.Verify()

[事实]
公共异步无效运行\u后台\u任务\u成功()
{
//安排
IServiceCollection服务=新的ServiceCollection();
services.AddHostedService();
var serviceProvider=services.BuildServiceProvider();
var service=serviceProvider.GetService()作为BackgroundManagerTask;
var isExecuted=false;
if(wait service.StartAsync(CancellationToken.None))
{
isExecuted=真;
}
等待任务。延迟(10000);
Assert.True(已执行);
wait service.StopAsync(CancellationToken.None);
}

我通常是这样做的。你提到你要去数据库更新一些数据,所以我假设你希望这是来自
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));
}
[事实]
public void backgroundmanager rupdatingstatest()
{
//安排
Mock dbMock=new Mock();
dbMock.Setup(x=>x.updateMethingDB(It.IsAny())。返回(1);//从BusinessObject的updateMethingDB中的DML更新一行
BackgroundManager sut=新的BackgroundManager(dbMock.Object);//正在测试的系统。
//表演
等待sut.StartAsync(CancellationToken.None);
等待任务。延迟(500);//给测试一些时间执行。
wait sut.StopAsync(CancellationToken.None);//停止后台服务。
//断言
Verify(x=>x.updateMethingDB(It.IsAny()),Times.justice(1));
}
在上面,我们通过模拟数据访问调用并验证它是否只被调用了一次来测试对数据库的更新

当然,您可以使用并断言任何其他要验证的依赖项来模拟任何其他依赖项

[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));
}