using AsbCloudInfrastructure.Background; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using System; using System.Threading; using System.Threading.Tasks; using Xunit; namespace AsbCloudWebApi.Tests.Services { public class WorkTest { private IServiceProvider provider; public WorkTest() { provider = Substitute.For(); var serviceScope = Substitute.For(); var serviceScopeFactory = Substitute.For(); serviceScopeFactory.CreateScope().Returns(serviceScope); ((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory); } [Fact] public async Task Work_done_with_success() { Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) => Task.CompletedTask; var work = Work.CreateByDelegate("", workAction); //act var begin = DateTime.Now; await work.Start(provider, CancellationToken.None); var done = DateTime.Now; var executionTime = done - begin; //assert Assert.Equal(1, work.CountComplete); Assert.Equal(1, work.CountStart); Assert.Equal(0, work.CountErrors); Assert.Null(work.CurrentState); Assert.Null(work.LastError); var lastState = work.LastComplete; Assert.NotNull(lastState); Assert.InRange(lastState.Start, begin, done - 0.5 * executionTime); Assert.InRange(lastState.End, done - 0.5 * executionTime, done); Assert.InRange(lastState.ExecutionTime, TimeSpan.Zero, executionTime); } [Fact] public async Task Work_calls_callback() { var expectedState = "42"; var expectedProgress = 42d; var timeout = TimeSpan.FromMilliseconds(40); Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { callback.Invoke(expectedState, expectedProgress); return Task.Delay(timeout); } var work = Work.CreateByDelegate("", workAction); //act var begin = DateTime.Now; _ = work.Start(provider, CancellationToken.None); await Task.Delay(timeout/3); //assert Assert.Equal(0, work.CountComplete); Assert.Equal(1, work.CountStart); Assert.Equal(0, work.CountErrors); Assert.NotNull(work.CurrentState); Assert.Null(work.LastComplete); Assert.Null(work.LastError); var currentState = work.CurrentState; Assert.NotNull(currentState); Assert.InRange(currentState.Start, begin, begin + timeout); Assert.InRange(currentState.StateUpdate, begin, begin + timeout); Assert.Equal(expectedState, currentState.State); Assert.Equal(expectedProgress, currentState.Progress); } [Fact] public async Task Work_fails_with_info() { var expectedState = "41"; var expectedErrorText = "42"; var minWorkTime = TimeSpan.FromMilliseconds(10); async Task workAction(string id, IServiceProvider services, Action callback, CancellationToken token) { await Task.Delay(minWorkTime); callback(expectedState, 0); throw new Exception(expectedErrorText); } var work = Work.CreateByDelegate("", workAction); //act var begin = DateTime.Now; await work.Start(provider, CancellationToken.None); //assert Assert.Equal(0, work.CountComplete); Assert.Equal(1, work.CountStart); Assert.Equal(1, work.CountErrors); Assert.Null(work.CurrentState); Assert.Null(work.LastComplete); var error = work.LastError; Assert.NotNull(error); Assert.InRange(error.Start, begin, DateTime.Now); Assert.InRange(error.End, begin, DateTime.Now); Assert.InRange(error.ExecutionTime, minWorkTime, DateTime.Now - begin); Assert.Contains(expectedErrorText, error.ErrorText, StringComparison.InvariantCultureIgnoreCase); Assert.Equal(expectedState, error.State); } } }