From ce118dc94c4de109fdcec9afc737b02a26b04cb8 Mon Sep 17 00:00:00 2001 From: geewee Date: Mon, 13 Sep 2021 15:42:57 +0200 Subject: [PATCH] tests work --- .../PeriodicTaskTestClasses.cs | 33 ++++++++ tests/PeriodicTasksTest.cs | 84 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 tests/IntegrationUtils/PeriodicTaskTestClasses.cs create mode 100644 tests/PeriodicTasksTest.cs diff --git a/tests/IntegrationUtils/PeriodicTaskTestClasses.cs b/tests/IntegrationUtils/PeriodicTaskTestClasses.cs new file mode 100644 index 0000000..3facca9 --- /dev/null +++ b/tests/IntegrationUtils/PeriodicTaskTestClasses.cs @@ -0,0 +1,33 @@ +namespace BetterHostedServices.Test.IntegrationUtils +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + public class CrashingPeriodicTask: IPeriodicTask + { + public async Task ExecuteAsync(CancellationToken stoppingToken) + { + await Task.Delay(50, stoppingToken); // Just to yield control + throw new Exception("oh no"); + } + } + + public class IncrementingThenCrashingPeriodicTask: IPeriodicTask + { + private readonly SingletonStateHolder singletonStateHolder; + + public IncrementingThenCrashingPeriodicTask(SingletonStateHolder singletonStateHolder) => this.singletonStateHolder = singletonStateHolder; + + public async Task ExecuteAsync(CancellationToken stoppingToken) + { + this.singletonStateHolder.Count += 1; + throw new Exception("oh no"); + } + } + + public class SingletonStateHolder + { + public int Count { get; set; } + } +} diff --git a/tests/PeriodicTasksTest.cs b/tests/PeriodicTasksTest.cs new file mode 100644 index 0000000..632fe24 --- /dev/null +++ b/tests/PeriodicTasksTest.cs @@ -0,0 +1,84 @@ +namespace BetterHostedServices.Test +{ + using System; + using System.Threading.Tasks; + using FluentAssertions; + using IntegrationUtils; + using Microsoft.AspNetCore.TestHost; + using Microsoft.Extensions.DependencyInjection; + using Xunit; + + public class PeriodicTasksTest + { + private readonly CustomWebApplicationFactory _factory; + + public PeriodicTasksTest() + { + _factory = new CustomWebApplicationFactory(); + } + + [Fact] + public async Task PeriodicTask_ShouldEndApplication_IfFailureModeIsSetToCrash() + { + // Arrange + var applicationEnder = new ApplicationEnderMock(); + + var factory = this._factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddTransient(s => applicationEnder); + services.AddPeriodicTask(PeriodicTaskFailureMode.CrashApplication, TimeSpan.FromSeconds(1)); + }); + }); + + var client = factory.CreateClient(); + // Act & assert - we should crash here at some point + + // Task is hella flaky because it depends on the internals of the IHostedService - try yielding a bunch of times + // to hope that it's done requesting application shutdown at this point + for (int i = 0; i < 10; i++) + { + await Task.Delay(50); + await Task.Yield(); + } + + // due to https://github.com/dotnet/aspnetcore/issues/25857 we can't test if the process is closed directly + applicationEnder.ShutDownRequested.Should().BeTrue(); + } + + [Fact] + public async Task PeriodicTask_ShouldContinueRunningTasks_IfFailureModeIsSetToRetry() + { + // Arrange + var applicationEnder = new ApplicationEnderMock(); + var stateHolder = new SingletonStateHolder(); + + var factory = this._factory.WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + services.AddTransient(s => applicationEnder); + services.AddPeriodicTask(PeriodicTaskFailureMode.RetryLater, TimeSpan.FromMilliseconds(50)); + services.AddSingleton(s => stateHolder); + }); + }); + + var client = factory.CreateClient(); + // Act & assert - we crash here after each invocation, but we truck on. The stateHolder should keep being incremented + + // Task is hella flaky because it depends on the internals of the IHostedService - try yielding a bunch of times + // to hope that it's done requesting application shutdown at this point + for (int i = 0; i < 10; i++) + { + await Task.Delay(100); // 1s ms all in all + await Task.Yield(); + } + + stateHolder.Count.Should().BeGreaterThan(5); + + // due to https://github.com/dotnet/aspnetcore/issues/25857 we can't test if the process is closed directly + applicationEnder.ShutDownRequested.Should().BeFalse(); + } + } +}