using System; using System.Reflection; using System.Threading; using System.Threading.Tasks; using AsbCloudInfrastructure.Background; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using Xunit; namespace AsbCloudWebApi.Tests.Background; public class BackgroundWorkerTest { private readonly IServiceProvider serviceProviderMock = Substitute.For(); private readonly IServiceScope serviceScopeMock = Substitute.For(); private readonly IServiceScopeFactory serviceScopeFactoryMock = Substitute.For(); private readonly BackgroundWorker backgroundWorker; public BackgroundWorkerTest() { serviceScopeFactoryMock.CreateScope().Returns(serviceScopeMock); ((ISupportRequiredService)serviceProviderMock).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactoryMock); backgroundWorker = new BackgroundWorker(serviceProviderMock); typeof(BackgroundWorker) .GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance) ?.SetValue(backgroundWorker, TimeSpan.FromMilliseconds(1)); } [Fact] public async Task Enqueue_ShouldReturn_WorkCount() { //arrange const int workCount = 10; var result = 0; Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { result++; return Task.Delay(1); } //act for (int i = 0; i < workCount; i++) { var work = Work.CreateByDelegate(i.ToString(), workAction); backgroundWorker.Enqueue(work); } await backgroundWorker.ExecuteTask; //assert Assert.Equal(workCount, result); } [Fact] public async Task Enqueue_Continues_AfterExceptions() { //arrange const int expectadResult = 42; var result = 0; Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { result = expectadResult; return Task.CompletedTask; } var goodWork = Work.CreateByDelegate("", workAction); Task failAction(string id, IServiceProvider services, Action callback, CancellationToken token) => throw new Exception(); var badWork = Work.CreateByDelegate("", failAction); badWork.OnErrorAsync = (id, exception, token) => throw new Exception(); //act backgroundWorker.Enqueue(badWork); backgroundWorker.Enqueue(goodWork); await backgroundWorker.ExecuteTask; //assert Assert.Equal(expectadResult, result); Assert.Equal(1, backgroundWorker.Felled.Count); Assert.Equal(1, backgroundWorker.Done.Count); } [Fact] public async Task TryRemoveFromQueue_ShouldReturn_True() { //arrange const int workCount = 5; var result = 0; Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { result++; return Task.Delay(10); } //act for (int i = 0; i < workCount; i++) { var work = Work.CreateByDelegate(i.ToString(), workAction); backgroundWorker.Enqueue(work); } var removed = backgroundWorker.TryRemoveFromQueue((workCount - 1).ToString()); await backgroundWorker.ExecuteTask; //assert Assert.True(removed); Assert.Equal(workCount - 1, result); Assert.Equal(workCount - 1, backgroundWorker.Done.Count); } }