diff --git a/tests/Trax.Scheduler.Tests.Integration/Trax.Scheduler.Tests.Integration.csproj b/tests/Trax.Scheduler.Tests.Integration/Trax.Scheduler.Tests.Integration.csproj index c3f6b53..36e7a89 100644 --- a/tests/Trax.Scheduler.Tests.Integration/Trax.Scheduler.Tests.Integration.csproj +++ b/tests/Trax.Scheduler.Tests.Integration/Trax.Scheduler.Tests.Integration.csproj @@ -16,6 +16,7 @@ + diff --git a/tests/Trax.Scheduler.Tests.Integration/UnitTests/SchedulerBuilderLambdaInvocationTests.cs b/tests/Trax.Scheduler.Tests.Integration/UnitTests/SchedulerBuilderLambdaInvocationTests.cs new file mode 100644 index 0000000..b280328 --- /dev/null +++ b/tests/Trax.Scheduler.Tests.Integration/UnitTests/SchedulerBuilderLambdaInvocationTests.cs @@ -0,0 +1,163 @@ +using FluentAssertions; +using LanguageExt; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using NUnit.Framework; +using Trax.Effect.Data.InMemory.Extensions; +using Trax.Effect.Extensions; +using Trax.Effect.Models.Manifest; +using Trax.Mediator.Extensions; +using Trax.Scheduler.Configuration; +using Trax.Scheduler.Extensions; +using Trax.Scheduler.Services.Scheduling; +using Trax.Scheduler.Services.TraxScheduler; +using Trax.Scheduler.Tests.Integration.Fakes.Trains; + +namespace Trax.Scheduler.Tests.Integration.UnitTests; + +/// +/// Exercises the ScheduleFunc lambda bodies inside SchedulerConfigurationBuilder by +/// invoking each pending manifest's closure against a substitute scheduler and +/// verifying it routes to the expected ITraxScheduler method. +/// +[TestFixture] +public class SchedulerBuilderLambdaInvocationTests +{ + private static SchedulerConfiguration ResolveConfiguration( + Action configure + ) + { + var services = new ServiceCollection(); + services.AddLogging(); + services.AddTrax(trax => + trax.AddEffects(effects => effects.UseInMemory()) + .AddMediator(typeof(AssemblyMarker).Assembly) + .AddScheduler(scheduler => + { + scheduler.UseInMemoryWorkers(); + configure(scheduler); + return scheduler; + }) + ); + using var provider = services.BuildServiceProvider(); + return provider.GetRequiredService(); + } + + [Test] + public async Task Schedule_LambdaInvocation_RoutesToScheduleAsync() + { + var config = ResolveConfiguration(s => + s.Schedule( + "ext-sched", + new SchedulerTestInput(), + Every.Minutes(5) + ) + ); + + var scheduler = Substitute.For(); + var dummyManifest = (Manifest) + System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Manifest)); + scheduler + .ScheduleAsync( + Arg.Any(), + Arg.Any(), + Arg.Any(), + Arg.Any?>(), + Arg.Any() + ) + .Returns(dummyManifest); + + var pending = config.PendingManifests.Single(m => m.ExternalId == "ext-sched"); + await pending.ScheduleFunc(scheduler, CancellationToken.None); + + await scheduler + .Received(1) + .ScheduleAsync( + "ext-sched", + Arg.Any(), + Arg.Any(), + Arg.Any?>(), + Arg.Any() + ); + } + + [Test] + public async Task ScheduleOnce_LambdaInvocation_RoutesToScheduleOnceAsync() + { + var config = ResolveConfiguration(s => + s.ScheduleOnce( + "once-ext", + new SchedulerTestInput(), + TimeSpan.FromMinutes(2) + ) + ); + + var scheduler = Substitute.For(); + var dummyManifest = (Manifest) + System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Manifest)); + scheduler + .ScheduleOnceAsync( + Arg.Any(), + Arg.Any(), + Arg.Any(), + Arg.Any?>(), + Arg.Any() + ) + .Returns(dummyManifest); + + var pending = config.PendingManifests.Single(m => m.ExternalId == "once-ext"); + await pending.ScheduleFunc(scheduler, CancellationToken.None); + + await scheduler + .Received(1) + .ScheduleOnceAsync( + "once-ext", + Arg.Any(), + TimeSpan.FromMinutes(2), + Arg.Any?>(), + Arg.Any() + ); + } + + [Test] + public async Task Include_LambdaInvocation_RoutesToScheduleDependentAsync() + { + var config = ResolveConfiguration(s => + s.Schedule( + "root-x", + new SchedulerTestInput(), + Every.Minutes(5) + ) + .Include( + "branch-x", + new SchedulerTestInput() + ) + ); + + var scheduler = Substitute.For(); + var dummyManifest = (Manifest) + System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Manifest)); + scheduler + .ScheduleDependentAsync( + Arg.Any(), + Arg.Any(), + Arg.Any(), + Arg.Any?>(), + Arg.Any() + ) + .Returns(dummyManifest); + + var pending = config.PendingManifests.Single(m => m.ExternalId == "branch-x"); + await pending.ScheduleFunc(scheduler, CancellationToken.None); + + await scheduler + .Received(1) + .ScheduleDependentAsync( + "branch-x", + Arg.Any(), + "root-x", + Arg.Any?>(), + Arg.Any() + ); + } +}