using AsbCloudInfrastructure.Background; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using System; using System.Reflection; using System.Threading; using System.Threading.Tasks; using Xunit; namespace AsbCloudWebApi.Tests.Services; public class BackgroundWorkerTest { private IServiceProvider provider; private BackgroundWorker service; public BackgroundWorkerTest() { provider = Substitute.For(); var serviceScope = Substitute.For(); var serviceScopeFactory = Substitute.For(); serviceScopeFactory.CreateScope().Returns(serviceScope); ((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory); service = new BackgroundWorker(provider); typeof(BackgroundWorker) .GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(service, TimeSpan.FromMilliseconds(1)); } [Fact] public async Task Enqueue_n_works() { var 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); service.Enqueue(work); } await service.ExecuteTask; //assert Assert.Equal(workCount, result); } [Fact] public async Task Enqueue_continues_after_exceptions() { var 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 service.Enqueue(badWork); service.Enqueue(goodWork); await service.ExecuteTask; //assert Assert.Equal(expectadResult, result); Assert.Equal(1, service.Felled.Count); Assert.Equal(1, service.Done.Count); } [Fact] public async Task TryRemove() { var 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); service.Enqueue(work); } var removed = service.TryRemoveFromQueue((workCount - 1).ToString()); await service.ExecuteTask; //assert Assert.True(removed); Assert.Equal(workCount - 1, result); Assert.Equal(workCount - 1, service.Done.Count); } }