using System; using System.Diagnostics; using System.Reflection; using System.Threading; using System.Threading.Tasks; using AsbCloudInfrastructure.Background; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using Xunit; namespace AsbCloudInfrastructure.Tests.Background; //TODO: нужно поправить тесты, иногда они не проходят public class PeriodicBackgroundWorkerTest { private IServiceProvider provider; private PeriodicBackgroundWorker service; public PeriodicBackgroundWorkerTest() { provider = Substitute.For(); var serviceScope = Substitute.For(); var serviceScopeFactory = Substitute.For(); serviceScopeFactory.CreateScope().Returns(serviceScope); ((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory); service = new PeriodicBackgroundWorker(provider); typeof(PeriodicBackgroundWorker) .GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance)? .SetValue(service, TimeSpan.FromMilliseconds(1)); typeof(PeriodicBackgroundWorker) .GetField("executePeriod", BindingFlags.NonPublic | BindingFlags.Instance)? .SetValue(service, TimeSpan.FromMilliseconds(1)); } [Fact] public async Task WorkRunsTwice_ShouldReturn_WorkCount() { const int workCount = 2; const double periodMs = 100d; var period = TimeSpan.FromMilliseconds(periodMs); var result = 0; Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { result++; return Task.CompletedTask; } //act var work = Work.CreateByDelegate("", workAction); var stopwatch = Stopwatch.StartNew(); service.Add(work, period); var delay = periodMs / 20 + periodMs * workCount - stopwatch.ElapsedMilliseconds; await Task.Delay(TimeSpan.FromMilliseconds(delay)); //assert Assert.True(workCount <= result); } [Fact] public async Task Enqueue_Continues_AfterExceptions() { var expectadResult = 42; var result = 0; using var semaphore = new SemaphoreSlim(0, 1); Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { result = expectadResult; semaphore.Release(); 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.Add(badWork, TimeSpan.FromSeconds(2)); service.Add(goodWork, TimeSpan.FromSeconds(2)); await semaphore.WaitAsync(4_100); //assert Assert.Equal(1, badWork.CountErrors); Assert.Equal(1, goodWork.CountComplete); Assert.Equal(1, goodWork.CountStart); Assert.Equal(expectadResult, result); } }