From ce35ef588f1a1c43d94e9c681c5d260163fb058b Mon Sep 17 00:00:00 2001 From: TekH Date: Fri, 16 Jan 2026 15:24:51 +0100 Subject: [PATCH] Add integration test project with MediatR procedure tests Added ReC.Tests project with integration tests for stored procedure commands and queries via MediatR, covering endpoints, actions, results, and profiles. Introduced a test base for DI/configuration, helper for private property access, and updated the solution to include the new test suite. Tests use NUnit and cover both positive and negative scenarios. --- ReC.sln | 9 +++ .../EndpointAuthProcedureTests.cs | 61 ++++++++++++++++ .../EndpointParamsProcedureTests.cs | 61 ++++++++++++++++ .../Endpoints/EndpointProcedureTests.cs | 61 ++++++++++++++++ .../Procedures/ProcedureExecutionTests.cs | 58 +++++++++++++++ .../Profile/ProfileProcedureTests.cs | 61 ++++++++++++++++ .../Application/Profile/ProfileQueryTests.cs | 43 +++++++++++ .../RecActions/RecActionProcedureTests.cs | 61 ++++++++++++++++ .../RecActions/RecActionQueryTests.cs | 55 ++++++++++++++ .../Application/RecApplicationTestBase.cs | 73 +++++++++++++++++++ .../Results/ResultProcedureTests.cs | 61 ++++++++++++++++ .../Application/Results/ResultQueryTests.cs | 34 +++++++++ .../Shared/ProcedureObjectHelper.cs | 22 ++++++ tests/ReC.Tests/ReC.Tests.csproj | 33 +++++++++ 14 files changed, 693 insertions(+) create mode 100644 tests/ReC.Tests/Application/EndpointAuth/EndpointAuthProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/EndpointParams/EndpointParamsProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/Endpoints/EndpointProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/Procedures/ProcedureExecutionTests.cs create mode 100644 tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs create mode 100644 tests/ReC.Tests/Application/RecActions/RecActionProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/RecActions/RecActionQueryTests.cs create mode 100644 tests/ReC.Tests/Application/RecApplicationTestBase.cs create mode 100644 tests/ReC.Tests/Application/Results/ResultProcedureTests.cs create mode 100644 tests/ReC.Tests/Application/Results/ResultQueryTests.cs create mode 100644 tests/ReC.Tests/Application/Shared/ProcedureObjectHelper.cs create mode 100644 tests/ReC.Tests/ReC.Tests.csproj diff --git a/ReC.sln b/ReC.sln index b83668d..a582c5d 100644 --- a/ReC.sln +++ b/ReC.sln @@ -26,6 +26,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "presentation", "presentatio EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{2CEF945E-94D6-4273-9BE1-20B628CD0A57}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8353C9B1-CC4A-4097-A936-C06D4C618415}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReC.Tests", "tests\ReC.Tests\ReC.Tests.csproj", "{457ED5AC-F4A0-41C3-9758-4A3C272EDC11}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -52,6 +56,10 @@ Global {DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA3A6BDD-8045-478F-860B-D1F0EB97F02B}.Release|Any CPU.Build.0 = Release|Any CPU + {457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {457ED5AC-F4A0-41C3-9758-4A3C272EDC11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -65,6 +73,7 @@ Global {3F88DACC-CEC0-4D9A-8BAA-37F67B02DC04} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} {3D6EF9B9-D00D-432A-8477-067902B5CE8E} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} {2CEF945E-94D6-4273-9BE1-20B628CD0A57} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {457ED5AC-F4A0-41C3-9758-4A3C272EDC11} = {8353C9B1-CC4A-4097-A936-C06D4C618415} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F7B09104-4072-4635-9492-9C7C68D96ABD} diff --git a/tests/ReC.Tests/Application/EndpointAuth/EndpointAuthProcedureTests.cs b/tests/ReC.Tests/Application/EndpointAuth/EndpointAuthProcedureTests.cs new file mode 100644 index 0000000..d02731a --- /dev/null +++ b/tests/ReC.Tests/Application/EndpointAuth/EndpointAuthProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.EndpointAuth.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.EndpointAuth; + +[TestFixture] +public class EndpointAuthProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertEndpointAuthProcedure_runs_via_mediator() + { + var procedure = new InsertEndpointAuthProcedure { Active = true, Description = "auth", TypeId = 1, ApiKey = "key", ApiValue = "value" }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateEndpointAuthProcedure_runs_via_mediator() + { + var procedure = new UpdateEndpointAuthProcedure { Active = false, Description = "auth-update", TypeId = 2 }; + var objectProc = procedure.ToObjectProcedure(15, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteEndpointAuthProcedure_runs_via_mediator() + { + var procedure = new DeleteEndpointAuthProcedure { Start = 3, End = 4, Force = false }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/EndpointParams/EndpointParamsProcedureTests.cs b/tests/ReC.Tests/Application/EndpointParams/EndpointParamsProcedureTests.cs new file mode 100644 index 0000000..5c5677c --- /dev/null +++ b/tests/ReC.Tests/Application/EndpointParams/EndpointParamsProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.EndpointParams.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.EndpointParams; + +[TestFixture] +public class EndpointParamsProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertEndpointParamsProcedure_runs_via_mediator() + { + var procedure = new InsertEndpointParamsProcedure { Active = true, Description = "param", GroupId = 1, Sequence = 1, Key = "k", Value = "v" }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateEndpointParamsProcedure_runs_via_mediator() + { + var procedure = new UpdateEndpointParamsProcedure { Active = false, Description = "param-update", GroupId = 2, Sequence = 2, Key = "k2", Value = "v2" }; + var objectProc = procedure.ToObjectProcedure(25, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteEndpointParamsProcedure_runs_via_mediator() + { + var procedure = new DeleteEndpointParamsProcedure { Start = 5, End = 6, Force = true }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/Endpoints/EndpointProcedureTests.cs b/tests/ReC.Tests/Application/Endpoints/EndpointProcedureTests.cs new file mode 100644 index 0000000..92c095b --- /dev/null +++ b/tests/ReC.Tests/Application/Endpoints/EndpointProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.Endpoints.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Endpoints; + +[TestFixture] +public class EndpointProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertEndpointProcedure_runs_via_mediator() + { + var procedure = new InsertEndpointProcedure { Active = true, Description = "desc", Uri = "http://example" }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateEndpointProcedure_runs_via_mediator() + { + var procedure = new UpdateEndpointProcedure { Active = false, Description = "updated", Uri = "http://updated" }; + var objectProc = procedure.ToObjectProcedure(12, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteEndpointProcedure_runs_via_mediator() + { + var procedure = new DeleteEndpointProcedure { Start = 1, End = 2, Force = true }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/Procedures/ProcedureExecutionTests.cs b/tests/ReC.Tests/Application/Procedures/ProcedureExecutionTests.cs new file mode 100644 index 0000000..a1aa65a --- /dev/null +++ b/tests/ReC.Tests/Application/Procedures/ProcedureExecutionTests.cs @@ -0,0 +1,58 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.Profile.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Procedures; + +[TestFixture] +public class ProcedureExecutionTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task ExecuteInsertProcedure_runs_with_addedWho() + { + var procedure = new InsertProfileProcedure { Name = "name" }; + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.ExecuteInsertProcedure(procedure, "ReC.Tests"); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task ExecuteUpdateProcedure_runs_with_changedWho() + { + var procedure = new UpdateProfileProcedure { Name = "updated" }; + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.ExecuteUpdateProcedure(procedure, 123, "ReC.Tests"); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task ExecuteDeleteProcedure_runs() + { + var procedure = new DeleteProfileProcedure { Start = 1, End = 2, Force = true }; + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.ExecuteDeleteProcedure(procedure); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs b/tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs new file mode 100644 index 0000000..448b59a --- /dev/null +++ b/tests/ReC.Tests/Application/Profile/ProfileProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.Profile.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Profile; + +[TestFixture] +public class ProfileProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertProfileProcedure_runs_via_mediator() + { + var procedure = new InsertProfileProcedure { Active = true, TypeId = 1, Name = "name", Mandantor = "man" }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateProfileProcedure_runs_via_mediator() + { + var procedure = new UpdateProfileProcedure { Active = false, TypeId = 2, Name = "updated", Mandantor = "man2" }; + var objectProc = procedure.ToObjectProcedure(45, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteProfileProcedure_runs_via_mediator() + { + var procedure = new DeleteProfileProcedure { Start = 9, End = 10, Force = false }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs b/tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs new file mode 100644 index 0000000..a2e6c33 --- /dev/null +++ b/tests/ReC.Tests/Application/Profile/ProfileQueryTests.cs @@ -0,0 +1,43 @@ +using System.Linq; +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Profile.Queries; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Profile; + +[TestFixture] +public class ProfileQueryTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task ReadProfileViewQuery_returns_profile_from_database() + { + var profileId = Configuration.GetValue("FakeProfileId"); + Assert.That(profileId, Is.Not.Null.And.GreaterThan(0), "FakeProfileId must be configured in appsettings.json"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + + var profiles = await sender.Send(new ReadProfileViewQuery + { + Id = profileId, + IncludeActions = false + }); + + var profile = profiles.Single(); + + Assert.That(profile.Id, Is.EqualTo(profileId)); + Assert.That(profile.ProfileName, Is.Not.Null.And.Not.Empty); + Assert.That(profile.Active, Is.True); + } +} diff --git a/tests/ReC.Tests/Application/RecActions/RecActionProcedureTests.cs b/tests/ReC.Tests/Application/RecActions/RecActionProcedureTests.cs new file mode 100644 index 0000000..d02ceae --- /dev/null +++ b/tests/ReC.Tests/Application/RecActions/RecActionProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.RecActions.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.RecActions; + +[TestFixture] +public class RecActionProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertActionProcedure_runs_via_mediator() + { + var procedure = new InsertActionProcedure { ProfileId = 1, Active = true, Sequence = 1 }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateActionProcedure_runs_via_mediator() + { + var procedure = new UpdateActionProcedure { ProfileId = 2, Active = false, Sequence = 2 }; + var objectProc = procedure.ToObjectProcedure(35, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteActionProcedure_runs_via_mediator() + { + var procedure = new DeleteActionProcedure { Start = 7, End = 8, Force = true }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/RecActions/RecActionQueryTests.cs b/tests/ReC.Tests/Application/RecActions/RecActionQueryTests.cs new file mode 100644 index 0000000..0e89688 --- /dev/null +++ b/tests/ReC.Tests/Application/RecActions/RecActionQueryTests.cs @@ -0,0 +1,55 @@ +using System.Linq; +using System.Threading.Tasks; +using DigitalData.Core.Exceptions; +using MediatR; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.RecActions.Queries; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.RecActions; + +[TestFixture] +public class RecActionQueryTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task ReadRecActionViewQuery_returns_actions_for_profile() + { + var profileId = Configuration.GetValue("FakeProfileId"); + Assert.That(profileId, Is.Not.Null.And.GreaterThan(0), "FakeProfileId must be configured in appsettings.json"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + + var actions = await sender.Send(new ReadRecActionViewQuery + { + ProfileId = profileId + }); + + Assert.That(actions, Is.Not.Empty); + Assert.That(actions.All(a => a.ProfileId == profileId)); + } + + [Test] + public void ReadRecActionViewQuery_with_unknown_profile_throws_not_found() + { + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + + var invalidProfileId = long.MaxValue; + + Assert.ThrowsAsync(async () => + await sender.Send(new ReadRecActionViewQuery + { + ProfileId = invalidProfileId + })); + } +} diff --git a/tests/ReC.Tests/Application/RecApplicationTestBase.cs b/tests/ReC.Tests/Application/RecApplicationTestBase.cs new file mode 100644 index 0000000..09caea7 --- /dev/null +++ b/tests/ReC.Tests/Application/RecApplicationTestBase.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using ReC.Application; +using ReC.Application.Common.Options; +using ReC.Infrastructure; + +namespace ReC.Tests.Application; + +public abstract class RecApplicationTestBase : IDisposable +{ + protected RecApplicationTestBase() + { + Configuration = BuildConfiguration(); + ServiceProvider = BuildServiceProvider(Configuration); + } + + protected IConfiguration Configuration { get; } + + protected IServiceProvider ServiceProvider { get; } + + private static IConfiguration BuildConfiguration() + { + var appSettingsPath = LocateApiAppSettings(); + + return new ConfigurationBuilder() + .AddJsonFile(appSettingsPath, optional: false, reloadOnChange: false) + .Build(); + } + + private static IServiceProvider BuildServiceProvider(IConfiguration configuration) + { + var services = new ServiceCollection(); + + services.AddSingleton(configuration); + + services.AddRecServices(options => + { + options.LuckyPennySoftwareLicenseKey = configuration["LuckyPennySoftwareLicenseKey"]; + options.ConfigureRecActions(configuration.GetSection("RecAction")); + }); + + services.AddRecInfrastructure(opt => + { + opt.ConfigureDbContext((_, builder) => builder.UseSqlServer(configuration.GetConnectionString("Default"))); + }); + + return services.BuildServiceProvider(); + } + + private static string LocateApiAppSettings() + { + var current = new DirectoryInfo(AppContext.BaseDirectory); + while (current is not null) + { + var candidate = Path.Combine(current.FullName, "src", "ReC.API", "appsettings.json"); + if (File.Exists(candidate)) + return candidate; + + current = current.Parent; + } + + throw new FileNotFoundException("Could not locate src/ReC.API/appsettings.json from test base directory."); + } + + public void Dispose() + { + if (ServiceProvider is IDisposable disposable) + disposable.Dispose(); + } +} diff --git a/tests/ReC.Tests/Application/Results/ResultProcedureTests.cs b/tests/ReC.Tests/Application/Results/ResultProcedureTests.cs new file mode 100644 index 0000000..28d319d --- /dev/null +++ b/tests/ReC.Tests/Application/Results/ResultProcedureTests.cs @@ -0,0 +1,61 @@ +using System.Threading.Tasks; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Common.Procedures.DeleteProcedure; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; +using ReC.Application.Results.Commands; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Results; + +[TestFixture] +public class ResultProcedureTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public async Task InsertResultProcedure_runs_via_mediator() + { + var procedure = new InsertResultProcedure { ActionId = 1, StatusId = 200, Header = "h", Body = "b" }; + var objectProc = procedure.ToObjectProcedure("ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.GreaterThan(0)); + } + + [Test] + public async Task UpdateResultProcedure_runs_via_mediator() + { + var procedure = new UpdateResultProcedure { ActionId = 2, StatusId = 500, Header = "h2", Body = "b2" }; + var objectProc = procedure.ToObjectProcedure(55, "ReC.Tests"); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } + + [Test] + public async Task DeleteResultProcedure_runs_via_mediator() + { + var procedure = new DeleteResultProcedure { Start = 11, End = 12, Force = false }; + var objectProc = procedure.ToObjectProcedure(); + + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + var result = await sender.Send(objectProc); + + Assert.That(result, Is.EqualTo(0)); + } +} diff --git a/tests/ReC.Tests/Application/Results/ResultQueryTests.cs b/tests/ReC.Tests/Application/Results/ResultQueryTests.cs new file mode 100644 index 0000000..300623c --- /dev/null +++ b/tests/ReC.Tests/Application/Results/ResultQueryTests.cs @@ -0,0 +1,34 @@ +using DigitalData.Core.Exceptions; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using ReC.Application.Results.Queries; +using ReC.Tests.Application; + +namespace ReC.Tests.Application.Results; + +[TestFixture] +public class ResultQueryTests : RecApplicationTestBase +{ + private (ISender Sender, IServiceScope Scope) CreateScopedSender() + { + var scope = ServiceProvider.CreateScope(); + var sender = scope.ServiceProvider.GetRequiredService(); + return (sender, scope); + } + + [Test] + public void ReadResultViewQuery_with_unknown_action_throws_not_found() + { + var (sender, scope) = CreateScopedSender(); + using var _ = scope; + + var invalidActionId = long.MaxValue; + + Assert.ThrowsAsync(async () => + await sender.Send(new ReadResultViewQuery + { + ActionId = invalidActionId + })); + } +} diff --git a/tests/ReC.Tests/Application/Shared/ProcedureObjectHelper.cs b/tests/ReC.Tests/Application/Shared/ProcedureObjectHelper.cs new file mode 100644 index 0000000..1623b42 --- /dev/null +++ b/tests/ReC.Tests/Application/Shared/ProcedureObjectHelper.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using ReC.Application.Common.Procedures.InsertProcedure; +using ReC.Application.Common.Procedures.UpdateProcedure; + +namespace ReC.Tests.Application.Shared; + +internal static class ProcedureObjectHelper +{ + public static string? GetAddedWho(InsertObjectProcedure procedure) + { + return (string?)typeof(InsertObjectProcedure) + .GetProperty("AddedWho", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)? + .GetValue(procedure); + } + + public static string? GetChangedWho(UpdateObjectProcedure procedure) + { + return (string?)typeof(UpdateObjectProcedure) + .GetProperty("ChangedWho", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)? + .GetValue(procedure); + } +} diff --git a/tests/ReC.Tests/ReC.Tests.csproj b/tests/ReC.Tests/ReC.Tests.csproj new file mode 100644 index 0000000..ded8021 --- /dev/null +++ b/tests/ReC.Tests/ReC.Tests.csproj @@ -0,0 +1,33 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + + + + + +