From 3c179196b1558de1095939f8eca41bbbccc4b82d Mon Sep 17 00:00:00 2001 From: Craig Edmunds Date: Thu, 2 Jan 2025 17:41:49 +0000 Subject: [PATCH 1/2] CDMS-200 switches country ched searching to use country of origin CDMS-200 Refactored no match tests to re-use code Refactoring Test Fixtures Switched Analytics MaxVersion tests to use new fixtures Some small refactoring to remove some generics CDMS-200 adds additional decision tests, moves alvs decision check analytics into context so it appears in audit entry Refactoring fixtures Refactoring fixtures --- .../Btms.Analytics.Tests.csproj | 1 + .../ImportNotificationsByMaxVersionTests.cs | 2 +- .../MovementsByMaxVersionTests.cs | 193 +++++++++++++----- .../Extensions/MovementExtensions.cs | 6 +- .../ImportNotificationsAggregationService.cs | 11 +- Btms.Analytics/MovementExceptions.cs | 7 +- Btms.Analytics/MovementsAggregationService.cs | 6 +- .../AnalyticsTests.cs | 21 +- Btms.Backend.IntegrationTests/BaseApiTests.cs | 1 + .../Btms.Backend.IntegrationTests.csproj | 2 +- .../ChedPDuplicateDecisionTests.cs | 30 +-- .../DecisionTests/ChedPSimpleTests.cs | 144 +++++++++---- .../ChedPUpdatedNotificationTests.cs | 26 +-- ...nyItemTests.cs => NoMatchManyItemTests.cs} | 24 +-- .../NoMatchNoAlvsDecisionTests.cs | 63 ++++++ .../DecisionTests/NoMatchTests.cs | 76 +++++++ .../Extensions/HttpExtensions.cs | 14 -- Btms.Backend.IntegrationTests/GmrTests.cs | 8 +- .../Helpers/ApplicationFactory.cs | 1 + .../InMemoryScenarioApplicationFactory.cs | 3 +- .../Helpers/TestDataGeneratorFactory.cs | 1 + Btms.Backend.IntegrationTests/LinkingTests.cs | 1 - Btms.Backend.IntegrationTests/SmokeTests.cs | 11 +- .../Services/Linking/LinkingServiceTests.cs | 6 +- Btms.Business/Builders/MovementBuilder.cs | 95 +++++---- .../Extensions/MovementExtensions.cs | 15 +- .../Btms.Common.Testing.csproj | 25 +++ Btms.Consumers/DecisionsConsumer.cs | 8 +- Btms.Model/Cds/AlvsDecision.cs | 39 ++-- Btms.Model/Ipaffs/ImportNotification.cs | 2 +- Btms.Model/Movement.cs | 2 +- .../ImportNotificationMapper.g.cs | 3 + BtmsBackend.sln | 6 + TestDataGenerator/ClearanceRequestBuilder.cs | 3 +- TestDataGenerator/DecisionBuilder.cs | 7 +- TestDataGenerator/Helpers/BuilderHelpers.cs | 34 +++ TestDataGenerator/ScenarioGenerator.cs | 17 +- TestDataGenerator/Scenarios/CRNoMatch.cs | 135 ++++++++++++ .../CRNoMatchNoChecksScenarioGenerator.cs | 23 --- .../CRNoMatchNoDecisionScenarioGenerator.cs | 25 --- .../Scenarios/CRNoMatchScenarioGenerator.cs | 40 ---- .../ChedAManyCommoditiesScenarioGenerator.cs | 1 + .../ChedASimpleMatchScenarioGenerator.cs | 1 + .../BaseTest.cs | 49 +++++ .../BtmsClient.cs | 25 ++- .../Extensions/HttpExtensions.cs | 21 ++ .../Extensions/JsonExtensions.cs | 14 ++ .../Fixtures/BackendFixture.cs | 161 +++++++++++++++ .../Fixtures/BackendGeneratorFixture.cs | 13 ++ .../Fixtures/IIntegrationTestsFixture.cs | 14 ++ .../Fixtures/TestGeneratorFixture.cs | 65 ++++++ .../GeneratedResult.cs | 12 ++ .../JsonApiClient/JsonApiClient.cs | 2 +- .../JsonApiClient/JsonApiDocument.cs | 2 +- .../JsonApiClient/ManyItemsJsonApiDocument.cs | 2 +- .../JsonApiClient/Response.cs | 2 +- .../SingleItemJsonApiDocument.cs | 2 +- .../SyncJobResponse.cs | 2 +- ...enerator.IntegrationTesting.Backend.csproj | 27 +++ 59 files changed, 1142 insertions(+), 410 deletions(-) rename Btms.Backend.IntegrationTests/DecisionTests/{ManyItemTests.cs => NoMatchManyItemTests.cs} (54%) create mode 100644 Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs create mode 100644 Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs delete mode 100644 Btms.Backend.IntegrationTests/Extensions/HttpExtensions.cs create mode 100644 Btms.Common.Testing/Btms.Common.Testing.csproj create mode 100644 TestDataGenerator/Helpers/BuilderHelpers.cs create mode 100644 TestDataGenerator/Scenarios/CRNoMatch.cs delete mode 100644 TestDataGenerator/Scenarios/CRNoMatchNoChecksScenarioGenerator.cs delete mode 100644 TestDataGenerator/Scenarios/CRNoMatchNoDecisionScenarioGenerator.cs delete mode 100644 TestDataGenerator/Scenarios/CRNoMatchScenarioGenerator.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/BaseTest.cs rename {Btms.Backend.IntegrationTests/Helpers => TestGenerator.IntegrationTesting.Backend}/BtmsClient.cs (81%) create mode 100644 TestGenerator.IntegrationTesting.Backend/Extensions/HttpExtensions.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/Extensions/JsonExtensions.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/Fixtures/BackendGeneratorFixture.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/Fixtures/IIntegrationTestsFixture.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/Fixtures/TestGeneratorFixture.cs create mode 100644 TestGenerator.IntegrationTesting.Backend/GeneratedResult.cs rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/JsonApiClient/JsonApiClient.cs (98%) rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/JsonApiClient/JsonApiDocument.cs (93%) rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/JsonApiClient/ManyItemsJsonApiDocument.cs (85%) rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/JsonApiClient/Response.cs (82%) rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/JsonApiClient/SingleItemJsonApiDocument.cs (83%) rename {Btms.Backend.IntegrationTests => TestGenerator.IntegrationTesting.Backend}/SyncJobResponse.cs (91%) create mode 100644 TestGenerator.IntegrationTesting.Backend/TestGenerator.IntegrationTesting.Backend.csproj diff --git a/Btms.Analytics.Tests/Btms.Analytics.Tests.csproj b/Btms.Analytics.Tests/Btms.Analytics.Tests.csproj index b612975b..9e324cd9 100644 --- a/Btms.Analytics.Tests/Btms.Analytics.Tests.csproj +++ b/Btms.Analytics.Tests/Btms.Analytics.Tests.csproj @@ -40,6 +40,7 @@ + diff --git a/Btms.Analytics.Tests/ImportNotificationsByMaxVersionTests.cs b/Btms.Analytics.Tests/ImportNotificationsByMaxVersionTests.cs index d7ff84da..c6cd032b 100644 --- a/Btms.Analytics.Tests/ImportNotificationsByMaxVersionTests.cs +++ b/Btms.Analytics.Tests/ImportNotificationsByMaxVersionTests.cs @@ -68,7 +68,7 @@ public async Task WhenCalledWithCountry_ReturnsResults() { testOutputHelper.WriteLine("Querying for aggregated data"); var result = (await basicSampleDataTestFixture.GetImportNotificationsAggregationService(testOutputHelper) - .ByMaxVersion(DateTime.Now.NextHour().AddDays(-2), DateTime.Now.NextHour(), country: "AL")); + .ByMaxVersion(DateTime.Now.NextHour().AddDays(-2), DateTime.Now.NextHour(), country: "ES")); testOutputHelper.WriteLine($"{result.Values.Count} aggregated items found"); diff --git a/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs b/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs index 9f117a60..d3b9951f 100644 --- a/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs +++ b/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs @@ -1,78 +1,159 @@ -using Btms.Common.Extensions; +using Btms.Model.Ipaffs; using FluentAssertions; +using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend; +using TestGenerator.IntegrationTesting.Backend.Extensions; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; using Xunit.Abstractions; -using Btms.Analytics.Tests.Fixtures; -using Btms.Model.Ipaffs; - namespace Btms.Analytics.Tests; -[Collection(nameof(BasicSampleDataTestCollection))] -public class MovementsByMaxVersionTests( - BasicSampleDataTestFixture basicSampleDataTestFixture, - ITestOutputHelper testOutputHelper) +// [Collection(nameof(BasicSampleDataTestCollection))] +// public class MovementsByMaxVersionTests( +// BasicSampleDataTestFixture basicSampleDataTestFixture, +// ITestOutputHelper testOutputHelper) +public class MovementsByMaxVersionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) + : BaseTest(testOutputHelper, generatorFixture, backendFixture) { - // [Fact] - // public async Task WhenCalledLastWeek_ReturnExpectedAggregation() - // { - // testOutputHelper.WriteLine("Querying for aggregated data"); - // var result = (await basicSampleDataTestFixture.GetMovementsAggregationService(testOutputHelper) - // .ByStatus(DateTime.Today.WeekAgo(), DateTime.Today.Tomorrow())); - // - // testOutputHelper.WriteLine("{0} aggregated items found", result.Values.Count); - // - // result.Values.Count.Should().Be(2); - // result.Values.Keys.Order().Should().Equal("Linked", "Not Linked"); - // } - // - // [Fact] - // public async Task WhenCalledLast48Hours_ReturnExpectedAggregation() - // { - // testOutputHelper.WriteLine("Querying for aggregated data"); - // var result = (await basicSampleDataTestFixture.GetMovementsAggregationService(testOutputHelper) - // .ByStatus(DateTime.Now.NextHour().AddDays(-2), DateTime.Now.NextHour())); - // - // testOutputHelper.WriteLine($"{result.Values.Count} aggregated items found"); - // - // result.Values.Count.Should().Be(2); - // result.Values.Keys.Order().Should().Equal("Linked", "Not Linked"); - // } - // - // [Fact] - // public async Task WhenCalledWithTimePeriodYieldingNoResults_ReturnEmptyAggregation() - // { - // testOutputHelper.WriteLine("Querying for aggregated data"); - // var result = (await basicSampleDataTestFixture.GetMovementsAggregationService(testOutputHelper) - // .ByStatus(DateTime.MaxValue.AddDays(-1), DateTime.MaxValue)); - // - // testOutputHelper.WriteLine($"{result.Values.Count} aggregated items found"); - // - // result.Values.Count.Should().Be(2); - // result.Values.Keys.Order().Should().Equal("Linked", "Not Linked"); - // } + + [Fact] + public async Task WhenCalled_ReturnsResults() + { + TestOutputHelper.WriteLine("Querying for aggregated data"); + + var result = await BackendFixture + .BtmsClient + .GetAnalyticsDashboard(["movementsByMaxEntryVersion"], + dateFrom:DateTime.Today.AddDays(-1), + dateTo:DateTime.Today.AddDays(1)); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); + + var charts = await result.ToJsonDictionary(); + + TestOutputHelper.WriteLine($"movementsByMaxEntryVersion keys : {charts["movementsByMaxEntryVersion"].GetKeys()}"); + TestOutputHelper.WriteLine($"result keys : {charts["movementsByMaxEntryVersion"]["values"]!.GetKeys()}"); + + charts["movementsByMaxEntryVersion"]["values"]! + .GetKeys() + .Length.Should().Be(1); + + var val = charts["movementsByMaxEntryVersion"]["values"]!["1"]! + .GetValue() + .Should() + .Be(1); + } [Fact] public async Task WhenCalledWithChedType_ReturnsResults() { - testOutputHelper.WriteLine("Querying for aggregated data"); - var result = (await basicSampleDataTestFixture.GetMovementsAggregationService(testOutputHelper) - .ByMaxVersion(DateTime.Now.NextHour().AddDays(-2), DateTime.Now.NextHour(), chedTypes: [ImportNotificationTypeEnum.Cveda])); + TestOutputHelper.WriteLine("Querying for aggregated data"); + + var result = await BackendFixture + .BtmsClient + .GetAnalyticsDashboard(["movementsByMaxEntryVersion"], + dateFrom:DateTime.Today.AddDays(-1), + dateTo:DateTime.Today.AddDays(1), + chedTypes: [ImportNotificationTypeEnum.Cvedp]); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); + + var charts = await result.ToJsonDictionary(); + + TestOutputHelper.WriteLine($"movementsByMaxEntryVersion keys : {charts["movementsByMaxEntryVersion"].GetKeys()}"); + TestOutputHelper.WriteLine($"result keys : {charts["movementsByMaxEntryVersion"]["values"]!.GetKeys()}"); + + charts["movementsByMaxEntryVersion"]["values"]! + .GetKeys() + .Length.Should().Be(1); + + var val = charts["movementsByMaxEntryVersion"]["values"]!["1"]! + .GetValue() + .Should() + .Be(1); + } + + [Fact] + public async Task WhenCalledWithWrongChedType_ReturnsResults() + { + TestOutputHelper.WriteLine("Querying for aggregated data"); - testOutputHelper.WriteLine($"{result.Values.Count} aggregated items found"); + var result = await BackendFixture + .BtmsClient + .GetAnalyticsDashboard(["movementsByMaxEntryVersion"], + dateFrom:DateTime.Today.AddDays(-1), + dateTo:DateTime.Today.AddDays(1), + chedTypes: [ImportNotificationTypeEnum.Cveda]); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); + + var charts = await result.ToJsonDictionary(); - result.Values.Count.Should().Be(2); + TestOutputHelper.WriteLine($"movementsByMaxEntryVersion keys : {charts["movementsByMaxEntryVersion"].GetKeys()}"); + TestOutputHelper.WriteLine($"result keys : {charts["movementsByMaxEntryVersion"]["values"]!.GetKeys()}"); + + charts["movementsByMaxEntryVersion"]["values"]! + .GetKeys() + .Length.Should().Be(0); } [Fact] public async Task WhenCalledWithCountry_ReturnsResults() { - testOutputHelper.WriteLine("Querying for aggregated data"); - var result = (await basicSampleDataTestFixture.GetMovementsAggregationService(testOutputHelper) - .ByMaxVersion(DateTime.Now.NextHour().AddDays(-2), DateTime.Now.NextHour(), country: "AL")); + TestOutputHelper.WriteLine("Querying for aggregated data"); + + var result = await BackendFixture + .BtmsClient + .GetAnalyticsDashboard(["movementsByMaxEntryVersion"], + dateFrom:DateTime.Today.AddDays(-1), + dateTo:DateTime.Today.AddDays(1), + country:"FR"); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); + + var charts = await result.ToJsonDictionary(); + + TestOutputHelper.WriteLine($"movementsByMaxEntryVersion keys : {charts["movementsByMaxEntryVersion"].GetKeys()}"); + TestOutputHelper.WriteLine($"result keys : {charts["movementsByMaxEntryVersion"]["values"]!.GetKeys()}"); + + charts["movementsByMaxEntryVersion"]["values"]! + .GetKeys() + .Length.Should().Be(1); + + var val = charts["movementsByMaxEntryVersion"]["values"]!["1"]! + .GetValue() + .Should() + .Be(1); + } + + + [Fact] + public async Task WhenCalledWithWrongCountry_ReturnsResults() + { + TestOutputHelper.WriteLine("Querying for aggregated data"); - testOutputHelper.WriteLine($"{result.Values.Count} aggregated items found"); + var result = await BackendFixture + .BtmsClient + .GetAnalyticsDashboard(["movementsByMaxEntryVersion"], + dateFrom:DateTime.Today.AddDays(-1), + dateTo:DateTime.Today.AddDays(1), + country:"ES"); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); - result.Values.Count.Should().Be(1); + var charts = await result.ToJsonDictionary(); + + TestOutputHelper.WriteLine($"movementsByMaxEntryVersion keys : {charts["movementsByMaxEntryVersion"].GetKeys()}"); + TestOutputHelper.WriteLine($"result keys : {charts["movementsByMaxEntryVersion"]["values"]!.GetKeys()}"); + + charts["movementsByMaxEntryVersion"]["values"]! + .GetKeys() + .Length.Should().Be(0); } } \ No newline at end of file diff --git a/Btms.Analytics/Extensions/MovementExtensions.cs b/Btms.Analytics/Extensions/MovementExtensions.cs index 4da3dc1b..bd515e6f 100644 --- a/Btms.Analytics/Extensions/MovementExtensions.cs +++ b/Btms.Analytics/Extensions/MovementExtensions.cs @@ -12,8 +12,8 @@ public static IQueryable WhereFilteredByCreatedDateAndParams(this IQue .Where(m => (m.CreatedSource >= from && m.CreatedSource < to) && (country == null || m.DispatchCountryCode == country) && (chedTypes == null || !chedTypes!.Any() || - !m.AlvsDecisionStatus!.Context!.ChedTypes!.Any() || - m.AlvsDecisionStatus!.Context!.ChedTypes!.Any(c => chedTypes!.Contains(c)))); + !m.BtmsStatus.ChedTypes!.Any() || + m.BtmsStatus.ChedTypes!.Any(c => chedTypes!.Contains(c)))); } @@ -31,7 +31,7 @@ public static IQueryable SelectLinkStatus(this IQueryabl Movement = m, CreatedSource = m.CreatedSource!.Value, Description = - m.Status.LinkStatus + m.BtmsStatus.LinkStatus // m.Relationships.Notifications.Data.Count > 0 ? "Linked" : // m.AlvsDecisionStatus!.Context!.AlvsCheckStatus!.AnyMatch ? "Investigate" : // "Not Linked" diff --git a/Btms.Analytics/ImportNotificationsAggregationService.cs b/Btms.Analytics/ImportNotificationsAggregationService.cs index 3110afc1..0dd9ebea 100644 --- a/Btms.Analytics/ImportNotificationsAggregationService.cs +++ b/Btms.Analytics/ImportNotificationsAggregationService.cs @@ -120,18 +120,9 @@ public Task ByMaxVersion(DateTime from, DateTime to, Import var data = context .Notifications .Where(n => (n.CreatedSource >= from && n.CreatedSource < to) - && (country == null || n.PartOne!.Route!.TransitingStates!.Contains(country)) - + && (country == null || n.CommoditiesSummary!.CountryOfOrigin! == country) && (chedTypes == null || chedTypes!.Length == 0 || n.ImportNotificationType == null || chedTypes!.Contains(n.ImportNotificationType!.Value)) ) - - // .Select(n => new { Notification = n, IsChedTypeMatch = chedTypes == null || n.ImportNotificationType == null || Array.IndexOf(chedTypes!, n.ImportNotificationType) > -1 }) - // .Where(n => (n.Notification.CreatedSource >= from && n.Notification.CreatedSource < to) - // && (country == null || n.Notification.PartOne!.Route!.TransitingStates!.Contains(country)) - // && n.IsChedTypeMatch - // ) - // .Select(n => n.Notification) - .GroupBy(n => new { MaxVersion = n.AuditEntries.Where(a => a.CreatedBy == "Ipaffs").Max(a => a.Version ) }) diff --git a/Btms.Analytics/MovementExceptions.cs b/Btms.Analytics/MovementExceptions.cs index bca93c76..fdbee4f5 100644 --- a/Btms.Analytics/MovementExceptions.cs +++ b/Btms.Analytics/MovementExceptions.cs @@ -18,6 +18,7 @@ public class MovementExceptions(IMongoDbContext context, ILogger logger) var simplifiedMovementView = context .Movements .WhereFilteredByCreatedDateAndParams(from, to, chedTypes, country) + .Where(m => !m.BtmsStatus.Linked) .Select(m => new { // TODO - we should think about pre-calculating this stuff and storing it on the movement... @@ -29,9 +30,8 @@ public class MovementExceptions(IMongoDbContext context, ILogger logger) MaxEntryVersion = m.ClearanceRequests.Max(c => c.Header!.EntryVersionNumber) ?? 0, LinkedCheds = m.Relationships.Notifications.Data.Count, ItemCount = m.Items.Count, - ChedTypes = m.AlvsDecisionStatus.Context.ChedTypes, - // HasMatchDecisions = m.AlvsDecisionStatus.Context.AlvsCheckStatus != null && m.AlvsDecisionStatus.Context.AlvsCheckStatus.AnyMatch, - Status = m.Status, + ChedTypes = m.BtmsStatus.ChedTypes, + Status = m.BtmsStatus, DecisionMatched = !m.AlvsDecisionStatus.Decisions .OrderBy(d => d.Context.AlvsDecisionNumber) .Reverse() @@ -51,7 +51,6 @@ public class MovementExceptions(IMongoDbContext context, ILogger logger) LinkedCheds = m.LinkedCheds, ItemCount = m.ItemCount, ChedTypes = m.ChedTypes, - // HasMatchDecisions = m.HasMatchDecisions, Status = m.Status, HasNotificationRelationships = m.HasNotificationRelationships, Total = m.MaxDecisionNumber + m.MaxEntryVersion + m.LinkedCheds + m.ItemCount, diff --git a/Btms.Analytics/MovementsAggregationService.cs b/Btms.Analytics/MovementsAggregationService.cs index a7555b78..d115a015 100644 --- a/Btms.Analytics/MovementsAggregationService.cs +++ b/Btms.Analytics/MovementsAggregationService.cs @@ -286,7 +286,7 @@ public Task> .WhereFilteredByCreatedDateAndParams(from, to, chedTypes, country) .SelectMany(m => m.AlvsDecisionStatus.Decisions.Select( d => new {Decision = d, Movement = m } )) - .SelectMany(d => d.Decision.Checks.Select(c => new { d.Decision, d.Movement, Check = c})) + .SelectMany(d => d.Decision.Context.Checks.Select(c => new { d.Decision, d.Movement, Check = c})) .GroupBy(d => new { d.Decision.Context.DecisionStatus, @@ -306,7 +306,7 @@ public Task> // Works var summary = new SingleSeriesDataset() { Values = mongoQuery - .GroupBy(q => q.Key.DecisionStatus ?? "TBC") + .GroupBy(q => q.Key.DecisionStatus ?? "Investigation Needed") .ToDictionary( g => g.Key, g => g.Sum(k => k.Count) @@ -320,7 +320,7 @@ public Task> { Fields = new Dictionary() { - { "Classification", a.Key.DecisionStatus ?? "TBC" }, + { "Classification", a.Key.DecisionStatus ?? "Investigation Needed" }, { "CheckCode", a.Key.CheckCode! }, { "AlvsDecisionCode", a.Key.AlvsDecisionCode! }, { "BtmsDecisionCode", a.Key.BtmsDecisionCode! } diff --git a/Btms.Backend.IntegrationTests/AnalyticsTests.cs b/Btms.Backend.IntegrationTests/AnalyticsTests.cs index 6e9dd337..a81e5592 100644 --- a/Btms.Backend.IntegrationTests/AnalyticsTests.cs +++ b/Btms.Backend.IntegrationTests/AnalyticsTests.cs @@ -1,18 +1,7 @@ -using System.Diagnostics.CodeAnalysis; -using Btms.Common.Extensions; -using Btms.Model; -using Btms.SyncJob; -using Btms.Backend.IntegrationTests.JsonApiClient; -using FluentAssertions; -using System.Net; -using System.Net.Http.Json; -using System.Text; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; using Btms.Backend.IntegrationTests.Extensions; using Btms.Backend.IntegrationTests.Helpers; -using Json.More; +using FluentAssertions; +using TestGenerator.IntegrationTesting.Backend.Extensions; using Xunit; using Xunit.Abstractions; @@ -27,7 +16,7 @@ public class AnalyticsTests(ApplicationFactory factory, ITestOutputHelper testOu public async Task GetIndividualMultiSeriesDatetimeChart() { //Act - var response = await Client.GetAnalyticsDashboard("importNotificationLinkingByCreated"); + var response = await Client.GetAnalyticsDashboard(["importNotificationLinkingByCreated"]); // Assert response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString()); @@ -44,7 +33,7 @@ public async Task GetIndividualMultiSeriesDatetimeChart() public async Task GetIndividualMultiSeriesChart() { //Act - var response = await Client.GetAnalyticsDashboard("lastMonthMovementsByItemCount"); + var response = await Client.GetAnalyticsDashboard(["lastMonthMovementsByItemCount"]); // Assert response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString()); @@ -61,7 +50,7 @@ public async Task GetIndividualMultiSeriesChart() public async Task GetIndividualSingleSeriesChart() { //Act - var response = await Client.GetAnalyticsDashboard("last7DaysImportNotificationsLinkingStatus"); + var response = await Client.GetAnalyticsDashboard(["last7DaysImportNotificationsLinkingStatus"]); // Assert response.IsSuccessStatusCode.Should().BeTrue(response.StatusCode.ToString()); diff --git a/Btms.Backend.IntegrationTests/BaseApiTests.cs b/Btms.Backend.IntegrationTests/BaseApiTests.cs index 59bb767d..3e63fd1c 100644 --- a/Btms.Backend.IntegrationTests/BaseApiTests.cs +++ b/Btms.Backend.IntegrationTests/BaseApiTests.cs @@ -10,6 +10,7 @@ using FluentAssertions; using idunno.Authentication.Basic; using Microsoft.AspNetCore.Mvc.Testing; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; using Xunit.Abstractions; [assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/Btms.Backend.IntegrationTests/Btms.Backend.IntegrationTests.csproj b/Btms.Backend.IntegrationTests/Btms.Backend.IntegrationTests.csproj index c5f40d92..fb85863f 100644 --- a/Btms.Backend.IntegrationTests/Btms.Backend.IntegrationTests.csproj +++ b/Btms.Backend.IntegrationTests/Btms.Backend.IntegrationTests.csproj @@ -19,7 +19,6 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -44,6 +43,7 @@ + diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs index 4b187bd4..7c27e1e0 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs @@ -1,32 +1,34 @@ -using Btms.Model; -using FluentAssertions; using Btms.Backend.IntegrationTests.Helpers; +using Btms.Model; using Btms.Types.Alvs; +using Btms.Types.Ipaffs; +using FluentAssertions; using TestDataGenerator.Scenarios.ChedP; +using TestGenerator.IntegrationTesting.Backend; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; using Xunit.Abstractions; namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class ChedPDuplicateDecisionTests(InMemoryScenarioApplicationFactory factory, ITestOutputHelper testOutputHelper) - : BaseApiTests(factory, testOutputHelper, "DecisionTests"), IClassFixture> -{ - - [Fact(Skip = "We currently import the duplicate alvs decision & store it on the movement")] - // [Fact] +public class ChedPDuplicateDecisionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) + : BaseTest(testOutputHelper, generatorFixture, backendFixture) +{ + // [Fact(Skip = "We currently import the duplicate alvs decision & store it on the movement")] + [Fact] public void SimpleChedPScenario_ShouldBeLinkedAndMatchDecision() { // Arrange - var loadedData = factory.LoadedData; + var loadedData = LoadedData; var chedPMovement = (AlvsClearanceRequest)loadedData.Single(d => - d is { message: AlvsClearanceRequest }) - .message; + d is { Message: AlvsClearanceRequest }) + .Message; - var chedPNotification = (Types.Ipaffs.ImportNotification)loadedData.Single(d => - d is { message: Types.Ipaffs.ImportNotification }) - .message; + var chedPNotification = (ImportNotification)loadedData.Single(d => + d is { Message: ImportNotification }) + .Message; // Act var jsonClientResponse = Client.AsJsonApiClient().GetById(chedPMovement!.Header!.EntryReference!, "api/movements"); diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs index c2c142c6..a0a4eda6 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs @@ -1,88 +1,97 @@ using Btms.Backend.IntegrationTests.Helpers; using Btms.Model; -using Btms.Model.Ipaffs; +using Btms.Types.Ipaffs; using FluentAssertions; using TestDataGenerator.Scenarios.ChedP; +using TestGenerator.IntegrationTesting.Backend; +using TestGenerator.IntegrationTesting.Backend.Extensions; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; using Xunit.Abstractions; -using ImportNotification = Btms.Types.Ipaffs.ImportNotification; +using ImportNotificationTypeEnum = Btms.Model.Ipaffs.ImportNotificationTypeEnum; namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class ChedPSimpleTests( - InMemoryScenarioApplicationFactory factory, - ITestOutputHelper testOutputHelper) - : BaseApiTests(factory, testOutputHelper, "DecisionTests"), - IClassFixture> +public class ChedPSimpleTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) + : BaseTest(testOutputHelper, generatorFixture, backendFixture) { + [Fact] - public void ShouldBeLinked() + public void ShouldHaveCorrectAlvsDecisions() { - // Act - var movementResource = Client.AsJsonApiClient() + // Assert + var movement = Client.AsJsonApiClient() .Get("api/movements") - .Data - .Single() - .Relationships!.Count.Should().Be(1); + .GetResourceObjects() + .Single(); + + movement.AlvsDecisionStatus.Decisions.Count.Should().Be(1); + + movement.AlvsDecisionStatus.Decisions + .First() + .Context.DecisionMatched + .Should().BeTrue(); } - + [Fact] - public void ShouldHaveCorrectDecisions() + public void ShouldHaveCorrectBtmsDecisions() { - var chedPNotification = (ImportNotification)factory - .LoadedData + var chedPNotification = (ImportNotification)LoadedData .Single(d => - d is { message: ImportNotification } + d is { Message: ImportNotification } ) - .message; - + .Message; + // Assert var movement = Client.AsJsonApiClient() .Get("api/movements") .GetResourceObjects() .Single(); - + movement.Decisions.Count.Should().Be(2); - movement.AlvsDecisionStatus.Decisions.Count.Should().Be(1); - - movement.AlvsDecisionStatus.Decisions - .First() - .Context.DecisionMatched - .Should().BeTrue(); - + var decisionWithLinkAndContext = movement.AuditEntries .Where(a => a is { CreatedBy: "Btms", Status: "Decision" }) .MaxBy(a => a.Version)!; - + decisionWithLinkAndContext.Context!.ImportNotifications .Should().NotBeNull(); - + decisionWithLinkAndContext.Context!.ImportNotifications! .Select(n => (n.Id, n.Version)) .Should() - .Equal((chedPNotification.ReferenceNumber!, 1)); + .Equal([ + ( chedPNotification.ReferenceNumber!, 1 ) + ]); } [Fact] public void ShouldHaveCorrectAuditTrail() { + // Assert var movement = Client.AsJsonApiClient() .Get("api/movements") .GetResourceObjects() .Single(); - + movement.AuditEntries .Select(a => (a.CreatedBy, a.Status, a.Version)) .Should() - .Equal(("Cds", "Created", 1), ("Btms", "Decision", 1), ("Btms", "Linked", null), ("Btms", "Decision", 2), - ("Alvs", "Decision", 1)); + .Equal([ + ("Cds", "Created", 1), + ("Btms", "Decision", 1), + ("Btms", "Linked", null), + ("Btms", "Decision", 2), + ("Alvs", "Decision", 1) + ]); } [Fact] public void ShouldHaveDecisionMatched() { + // Assert var movement = Client.AsJsonApiClient() .Get("api/movements") @@ -96,37 +105,64 @@ public void ShouldHaveDecisionMatched() .Should() .BeTrue(); } + + [Fact] + public void ShouldHaveDecisionStatus() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + movement + .AlvsDecisionStatus + .DecisionStatus + .Should() + .Be("Btms Made Same Decision As Alvs"); + } + [Fact] public void ShouldHaveChedType() { + // Assert var movement = Client.AsJsonApiClient() .Get("api/movements") .GetResourceObjects() .Single(); - - + movement - .Status + .BtmsStatus .ChedTypes .Should() .Equal(ImportNotificationTypeEnum.Cvedp); - - // - // movement - // .AlvsDecisionStatus - // .Context! - // .ChedTypes - // .Should() - // .Equal(ImportNotificationTypeEnum.Cvedp); } + + [Fact] + // [Fact(Skip = "Relationships aren't being deserialised correctly")] + // TODO : for some reason whilst jsonClientResponse contains the notification relationship, + // but movement from .GetResourceObject(s)(); doesn't! + public void ShouldBeLinked() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + movement.BtmsStatus.LinkStatus.Should().Be("Linked"); + } + + // [Fact] [Fact(Skip = "Relationships aren't being deserialised correctly")] // TODO : for some reason whilst jsonClientResponse contains the notification relationship, // but movement from .GetResourceObject(s)(); doesn't! public void ShouldHaveNotificationRelationships() { + // Assert var movement = Client.AsJsonApiClient() .Get("api/movements") @@ -137,4 +173,22 @@ public void ShouldHaveNotificationRelationships() .Relationships.Notifications.Data .Should().NotBeEmpty(); } + + + [Fact] + public async Task ShouldNotHaveExceptions() + { + // TestOutputHelper.WriteLine("Querying for aggregated data"); + + var result = await BackendFixture + .BtmsClient + .GetExceptions(); + + TestOutputHelper.WriteLine($"{result.StatusCode} status"); + result.IsSuccessStatusCode.Should().BeTrue(result.StatusCode.ToString()); + + (await result.GetString()) + .Should() + .Be("[]"); + } } \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ChedPUpdatedNotificationTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/ChedPUpdatedNotificationTests.cs index 0a293843..94b9e726 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ChedPUpdatedNotificationTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/ChedPUpdatedNotificationTests.cs @@ -1,24 +1,8 @@ -using System.Diagnostics.CodeAnalysis; -using Btms.Common.Extensions; -using Btms.Model; -using Btms.SyncJob; -using Btms.Backend.IntegrationTests.JsonApiClient; -using FluentAssertions; -using System.Net; -using System.Net.Http.Json; -using System.Text; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using Btms.Backend.IntegrationTests.Extensions; using Btms.Backend.IntegrationTests.Helpers; -using Btms.Business.Commands; -using Btms.Model.Cds; -using Btms.Model.Ipaffs; +using Btms.Model; using Btms.Types.Alvs; -using TestDataGenerator.Scenarios; -using Json.More; -using Microsoft.Extensions.Logging; +using Btms.Types.Ipaffs; +using FluentAssertions; using TestDataGenerator.Scenarios.ChedP; using Xunit; using Xunit.Abstractions; @@ -42,8 +26,8 @@ public void MultipleNotificationVersionScenario_ShouldBeLinkedAndMatchDecision() .message; // The scenario has multiple versions of the same notification so we just want one of them. - var chedPNotification = (Types.Ipaffs.ImportNotification)loadedData.FirstOrDefault(d => - d is { generator: MultiStepScenarioGenerator, message: Types.Ipaffs.ImportNotification }) + var chedPNotification = (ImportNotification)loadedData.FirstOrDefault(d => + d is { generator: MultiStepScenarioGenerator, message: ImportNotification }) .message; // Act diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ManyItemTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchManyItemTests.cs similarity index 54% rename from Btms.Backend.IntegrationTests/DecisionTests/ManyItemTests.cs rename to Btms.Backend.IntegrationTests/DecisionTests/NoMatchManyItemTests.cs index 187e02f2..d088cc3d 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ManyItemTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchManyItemTests.cs @@ -1,28 +1,9 @@ -using System.Diagnostics.CodeAnalysis; -using Btms.Common.Extensions; +using Btms.Backend.IntegrationTests.Helpers; using Btms.Model; -using Btms.SyncJob; -using Btms.Backend.IntegrationTests.JsonApiClient; using FluentAssertions; -using System.Net; -using System.Net.Http.Json; -using System.Text; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using Btms.Backend.IntegrationTests.Extensions; -using Btms.Backend.IntegrationTests.Helpers; -using Btms.Business.Commands; -using Btms.Model.Cds; -using Btms.Model.Ipaffs; -using Btms.Types.Alvs; using TestDataGenerator.Scenarios; -using Json.More; -using Microsoft.Extensions.Logging; -using TestDataGenerator.Scenarios.ChedP; using Xunit; using Xunit.Abstractions; -using ImportNotification = Btms.Types.Ipaffs.ImportNotification; namespace Btms.Backend.IntegrationTests.DecisionTests; @@ -40,7 +21,8 @@ public void ShouldHaveOneChedType() // .Data .GetResourceObjects() .Single() - .Status.ChedTypes!.Count().Should().Be(1); + .BtmsStatus.ChedTypes!.Count() + .Should().Be(1); } } \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs new file mode 100644 index 00000000..8cc64432 --- /dev/null +++ b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs @@ -0,0 +1,63 @@ +using Btms.Model; +using FluentAssertions; +using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend; +using TestGenerator.IntegrationTesting.Backend.Fixtures; +using Xunit; +using Xunit.Abstractions; + +namespace Btms.Backend.IntegrationTests.DecisionTests; + +[Trait("Category", "Integration")] +public class NoMatchNoAlvsDecisionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) + : BaseTest(testOutputHelper, generatorFixture, backendFixture)//, + // IClassFixture>, + // IClassFixture> +{ + + [Fact] + public void ShouldHaveNotificationRelationships() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement.BtmsStatus.LinkStatus.Should().Be("Not Linked"); + } + + [Fact] + public void ShouldHaveDecisionStatus() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement.AlvsDecisionStatus.DecisionStatus.Should().BeNull(); + } + + [Fact] + public void ShouldHaveDecisionMatched() + { + // var res = Client.AsJsonApiClient() + // .Get("api/movements"); + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement + .AlvsDecisionStatus + .Context! + .DecisionMatched + .Should() + .BeFalse(); + } +} \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs new file mode 100644 index 00000000..fd2a9e42 --- /dev/null +++ b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs @@ -0,0 +1,76 @@ +using Btms.Backend.IntegrationTests.Helpers; +using Btms.Model; +using FluentAssertions; +using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend; +using TestGenerator.IntegrationTesting.Backend.Fixtures; +using Xunit; +using Xunit.Abstractions; + +namespace Btms.Backend.IntegrationTests.DecisionTests; + +[Trait("Category", "Integration")] +public class NoMatchTests(ITestOutputHelper testOutputHelper, + // BackendGeneratorFixture backendGeneratorFixture) + BackendFixture backendFixture, + TestGeneratorFixture generatorFixture) + : BaseTest(testOutputHelper, generatorFixture, backendFixture)//, + ////IClassFixture>, + ////IClassFixture> +{ + + [Fact] + public void ShouldHaveNotificationRelationships() + { + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement.BtmsStatus.LinkStatus.Should().Be("Not Linked"); + } + + [Fact] + public void ShouldHaveAlvsDecision() + { + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement.AlvsDecisionStatus.Decisions.Count.Should().Be(1); + } + + [Fact] + public void ShouldHaveDecisionStatus() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement.AlvsDecisionStatus.DecisionStatus.Should().BeNull(); + } + + [Fact] + public void ShouldHaveDecisionMatchedFalse() + { + + // Assert + var movement = Client.AsJsonApiClient() + .Get("api/movements") + .GetResourceObjects() + .Single(); + + movement + .AlvsDecisionStatus + .Context! + .DecisionMatched + .Should() + .BeFalse(); + } +} \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/Extensions/HttpExtensions.cs b/Btms.Backend.IntegrationTests/Extensions/HttpExtensions.cs deleted file mode 100644 index 0c4ec614..00000000 --- a/Btms.Backend.IntegrationTests/Extensions/HttpExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Text.Json.Nodes; -using Btms.Common.Extensions; - -namespace Btms.Backend.IntegrationTests.Extensions; - -public static class HttpExtensions -{ - public static async Task> ToJsonDictionary(this HttpResponseMessage? response) - { - var responseDictionary = (await response!.Content.ReadAsStringAsync()).ToJsonDictionary(); - ArgumentNullException.ThrowIfNull(responseDictionary); - return responseDictionary; - } -} \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/GmrTests.cs b/Btms.Backend.IntegrationTests/GmrTests.cs index 4a13f778..7b95fd39 100644 --- a/Btms.Backend.IntegrationTests/GmrTests.cs +++ b/Btms.Backend.IntegrationTests/GmrTests.cs @@ -1,12 +1,8 @@ +using Btms.Backend.IntegrationTests.Helpers; using Btms.Business.Commands; -using Btms.Backend.IntegrationTests.JsonApiClient; using FluentAssertions; -using idunno.Authentication.Basic; using Microsoft.AspNetCore.Mvc.Testing; -using System.Net.Http.Headers; -using System.Text; -using System.Text.Json; -using Btms.Backend.IntegrationTests.Helpers; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; using Xunit.Abstractions; diff --git a/Btms.Backend.IntegrationTests/Helpers/ApplicationFactory.cs b/Btms.Backend.IntegrationTests/Helpers/ApplicationFactory.cs index 48cc3dad..72bbbd0b 100644 --- a/Btms.Backend.IntegrationTests/Helpers/ApplicationFactory.cs +++ b/Btms.Backend.IntegrationTests/Helpers/ApplicationFactory.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Options; using MongoDB.Bson.Serialization.Conventions; using MongoDB.Driver; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit.Abstractions; namespace Btms.Backend.IntegrationTests.Helpers; diff --git a/Btms.Backend.IntegrationTests/Helpers/InMemoryScenarioApplicationFactory.cs b/Btms.Backend.IntegrationTests/Helpers/InMemoryScenarioApplicationFactory.cs index 6cdab976..f43d77d8 100644 --- a/Btms.Backend.IntegrationTests/Helpers/InMemoryScenarioApplicationFactory.cs +++ b/Btms.Backend.IntegrationTests/Helpers/InMemoryScenarioApplicationFactory.cs @@ -23,6 +23,7 @@ using TestDataGenerator.Config; using TestDataGenerator.Extensions; using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit.Abstractions; namespace Btms.Backend.IntegrationTests.Helpers; @@ -70,7 +71,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) ConventionRegistry.Register("CamelCase", camelCaseConvention, _ => true); var dbName = string.IsNullOrEmpty(databaseName) ? Random.Shared.Next().ToString() : databaseName; - var db = client.GetDatabase($"Btms_MongoDb_{dbName}_Test"); + var db = client.GetDatabase($"Btms_{dbName}"); // TODO : Use our ILoggerFactory mongoDbContext = new MongoDbContext(db, new SerilogLoggerFactory()); diff --git a/Btms.Backend.IntegrationTests/Helpers/TestDataGeneratorFactory.cs b/Btms.Backend.IntegrationTests/Helpers/TestDataGeneratorFactory.cs index b62960da..a23a0444 100644 --- a/Btms.Backend.IntegrationTests/Helpers/TestDataGeneratorFactory.cs +++ b/Btms.Backend.IntegrationTests/Helpers/TestDataGeneratorFactory.cs @@ -25,6 +25,7 @@ using SlimMessageBus; using SlimMessageBus.Host; using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit.Sdk; namespace Btms.Backend.IntegrationTests.Helpers; diff --git a/Btms.Backend.IntegrationTests/LinkingTests.cs b/Btms.Backend.IntegrationTests/LinkingTests.cs index ebb7e945..deccbdfb 100644 --- a/Btms.Backend.IntegrationTests/LinkingTests.cs +++ b/Btms.Backend.IntegrationTests/LinkingTests.cs @@ -1,6 +1,5 @@ using Btms.Backend.IntegrationTests.Helpers; using Btms.Business.Commands; -using Btms.Backend.IntegrationTests.JsonApiClient; using FluentAssertions; using Xunit; using Xunit.Abstractions; diff --git a/Btms.Backend.IntegrationTests/SmokeTests.cs b/Btms.Backend.IntegrationTests/SmokeTests.cs index d44d43ec..569b7785 100644 --- a/Btms.Backend.IntegrationTests/SmokeTests.cs +++ b/Btms.Backend.IntegrationTests/SmokeTests.cs @@ -1,14 +1,13 @@ -using Btms.Business.Commands; -using Btms.Model; -using Btms.SyncJob; -using Btms.Backend.IntegrationTests.JsonApiClient; -using FluentAssertions; using System.Net; using System.Net.Http.Json; -using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using Btms.Backend.IntegrationTests.Helpers; +using Btms.Business.Commands; +using Btms.Model; +using Btms.SyncJob; +using FluentAssertions; +using TestGenerator.IntegrationTesting.Backend; using Xunit; using Xunit.Abstractions; diff --git a/Btms.Business.Tests/Services/Linking/LinkingServiceTests.cs b/Btms.Business.Tests/Services/Linking/LinkingServiceTests.cs index 043553a0..e7d55b00 100644 --- a/Btms.Business.Tests/Services/Linking/LinkingServiceTests.cs +++ b/Btms.Business.Tests/Services/Linking/LinkingServiceTests.cs @@ -297,7 +297,7 @@ private MovementLinkContext CreateMovementContext(Movement? movement, List { @@ -280,7 +277,7 @@ private AlvsDecision FindBtmsPairAndUpdate(CdsClearanceRequest clearanceRequest) // This is an initial implementation // we want to be smarter about how we 'pair' things, considering the same version of the import notifications - // can a BTMS decision be 'paired' to multiple ALVS decisions? + // Q : can a BTMS decision be 'paired' to multiple ALVS decisions? Probably not... var btmsDecision = _movement.Decisions? .Where(d => d.Header!.EntryVersionNumber == _movement.EntryVersionNumber) @@ -301,22 +298,22 @@ private AlvsDecision FindBtmsPairAndUpdate(CdsClearanceRequest clearanceRequest) AlvsDecisionNumber = clearanceRequest!.Header!.DecisionNumber!.Value, BtmsDecisionNumber = btmsDecision == null ? 0 : btmsDecision!.Header!.DecisionNumber!.Value, EntryVersionNumber = clearanceRequest!.Header!.EntryVersionNumber!.Value, - Paired = btmsDecision != null - }, - Checks = clearanceRequest - .Items!.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c })) - .Select(ic => - { - var decisionCode = btmsChecks == null ? null : btmsChecks!.GetValueOrDefault((ic.Item.ItemNumber!.Value, ic.Check.CheckCode!), null); - return new ItemCheck() + Paired = btmsDecision != null, + Checks = clearanceRequest + .Items!.SelectMany(i => i.Checks!.Select(c => new { Item = i, Check = c })) + .Select(ic => { - ItemNumber = ic.Item!.ItemNumber!.Value, - CheckCode = ic.Check!.CheckCode!, - AlvsDecisionCode = ic.Check!.DecisionCode!, - BtmsDecisionCode = decisionCode - }; - }) - .ToList() + var decisionCode = btmsChecks == null ? null : btmsChecks!.GetValueOrDefault((ic.Item.ItemNumber!.Value, ic.Check.CheckCode!), null); + return new ItemCheck() + { + ItemNumber = ic.Item!.ItemNumber!.Value, + CheckCode = ic.Check!.CheckCode!, + AlvsDecisionCode = ic.Check!.DecisionCode!, + BtmsDecisionCode = decisionCode + }; + }) + .ToList() + } }; if (btmsDecision != null) @@ -340,34 +337,36 @@ private void GuardNullMovement() private void CompareDecisions(AlvsDecision alvsDecision, CdsClearanceRequest btmsDecision) { GuardNullMovement(); + var alvsChecks = alvsDecision.Context.Checks; + var btmsChecks = alvsDecision.Context.Checks; alvsDecision.Context.AlvsCheckStatus = new StatusChecker() { - AllMatch = alvsDecision.Checks.All(c => !c.AlvsDecisionCode.StartsWith('X')), - AnyMatch = alvsDecision.Checks.Any(c => !c.AlvsDecisionCode.StartsWith('X')), - AllNoMatch = alvsDecision.Checks.All(c => c.AlvsDecisionCode.StartsWith('X')), - AnyNoMatch = alvsDecision.Checks.Any(c => c.AlvsDecisionCode.StartsWith('X')), - AllRefuse = alvsDecision.Checks.All(c => c.AlvsDecisionCode.StartsWith('N')), - AnyRefuse = alvsDecision.Checks.Any(c => c.AlvsDecisionCode.StartsWith('N')), - AllRelease = alvsDecision.Checks.All(c => c.AlvsDecisionCode.StartsWith('C')), - AnyRelease = alvsDecision.Checks.Any(c => c.AlvsDecisionCode.StartsWith('C')), - AllHold = alvsDecision.Checks.All(c => c.AlvsDecisionCode.StartsWith('H')), - AnyHold = alvsDecision.Checks.Any(c => c.AlvsDecisionCode.StartsWith('H')) + AllMatch = alvsChecks.All(c => !c.AlvsDecisionCode.StartsWith('X')), + AnyMatch = alvsChecks.Any(c => !c.AlvsDecisionCode.StartsWith('X')), + AllNoMatch = alvsChecks.All(c => c.AlvsDecisionCode.StartsWith('X')), + AnyNoMatch = alvsChecks.Any(c => c.AlvsDecisionCode.StartsWith('X')), + AllRefuse = alvsChecks.All(c => c.AlvsDecisionCode.StartsWith('N')), + AnyRefuse = alvsChecks.Any(c => c.AlvsDecisionCode.StartsWith('N')), + AllRelease = alvsChecks.All(c => c.AlvsDecisionCode.StartsWith('C')), + AnyRelease = alvsChecks.Any(c => c.AlvsDecisionCode.StartsWith('C')), + AllHold = alvsChecks.All(c => c.AlvsDecisionCode.StartsWith('H')), + AnyHold = alvsChecks.Any(c => c.AlvsDecisionCode.StartsWith('H')) }; alvsDecision.Context.BtmsCheckStatus = new StatusChecker() { - AllMatch = alvsDecision.Checks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), - AnyMatch = alvsDecision.Checks.Any(c => !(c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X'))), - AllNoMatch = alvsDecision.Checks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), - AnyNoMatch = alvsDecision.Checks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), - AllRefuse = alvsDecision.Checks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('N')), - AnyRefuse = alvsDecision.Checks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('N')), - AllRelease = alvsDecision.Checks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('C')), - AnyRelease = alvsDecision.Checks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('C')), - AllHold = alvsDecision.Checks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('H')), - AnyHold = alvsDecision.Checks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('H')) + AllMatch = btmsChecks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), + AnyMatch = btmsChecks.Any(c => !(c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X'))), + AllNoMatch = btmsChecks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), + AnyNoMatch = btmsChecks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('X')), + AllRefuse = btmsChecks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('N')), + AnyRefuse = btmsChecks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('N')), + AllRelease = btmsChecks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('C')), + AnyRelease = btmsChecks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('C')), + AllHold = btmsChecks.All(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('H')), + AnyHold = btmsChecks.Any(c => c.BtmsDecisionCode.HasValue() && c.BtmsDecisionCode.StartsWith('H')) }; var pairStatus = "Investigation Needed"; @@ -378,7 +377,7 @@ private void CompareDecisions(AlvsDecision alvsDecision, CdsClearanceRequest btm } else { - var checksMatch = alvsDecision.Checks.All(c => c.AlvsDecisionCode == c.BtmsDecisionCode); + var checksMatch = alvsChecks.All(c => c.AlvsDecisionCode == c.BtmsDecisionCode); if (checksMatch) { diff --git a/Btms.Business/Extensions/MovementExtensions.cs b/Btms.Business/Extensions/MovementExtensions.cs index c1e2e9e1..380cc858 100644 --- a/Btms.Business/Extensions/MovementExtensions.cs +++ b/Btms.Business/Extensions/MovementExtensions.cs @@ -1,4 +1,5 @@ using Btms.Model; +using Btms.Model.Cds; namespace Btms.Business.Extensions; @@ -6,18 +7,20 @@ public static class MovementExtensions { public static void AddLinkStatus(this Movement movement) { - var linkStatus = "Not Linked"; - + var linkStatus = MovementStatus.NotLinkedStatus; + var linked = false; + if (movement.Relationships.Notifications.Data.Count > 0) { - linkStatus = "Linked"; + linkStatus = MovementStatus.LinkedStatus; + linked = true; } else if (movement.AlvsDecisionStatus?.Context?.AlvsCheckStatus?.AnyMatch ?? false) { - linkStatus = "Investigate"; + linkStatus = MovementStatus.InvestigateStatus; } - movement.Status.LinkStatus = linkStatus; + movement.BtmsStatus.LinkStatus = linkStatus; + movement.BtmsStatus.Linked = linked; } - } \ No newline at end of file diff --git a/Btms.Common.Testing/Btms.Common.Testing.csproj b/Btms.Common.Testing/Btms.Common.Testing.csproj new file mode 100644 index 00000000..52ec16e6 --- /dev/null +++ b/Btms.Common.Testing/Btms.Common.Testing.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + diff --git a/Btms.Consumers/DecisionsConsumer.cs b/Btms.Consumers/DecisionsConsumer.cs index 4ea3e9b6..225b7e71 100644 --- a/Btms.Consumers/DecisionsConsumer.cs +++ b/Btms.Consumers/DecisionsConsumer.cs @@ -8,7 +8,7 @@ namespace Btms.Consumers; -public class DecisionsConsumer(IMongoDbContext dbContext, MovementBuilder movementBuilder) +public class DecisionsConsumer(IMongoDbContext dbContext, MovementBuilder existingMovementBuilder) : IConsumer, IConsumerWithContext { public async Task OnHandle(Decision message) @@ -21,15 +21,15 @@ public async Task OnHandle(Decision message) var auditId = Context.Headers["messageId"].ToString(); var notificationContext = Context.Headers.GetValueOrDefault("notifications", null) as List; - movementBuilder = movementBuilder + existingMovementBuilder = existingMovementBuilder .From(existingMovement!) .MergeDecision(auditId!, internalClearanceRequest, notificationContext); // .Build(); // var merged = existingMovement.MergeDecision(auditId!, internalClearanceRequest); - if (movementBuilder.HasChanges) + if (existingMovementBuilder.HasChanges) { - await dbContext.Movements.Update(movementBuilder.Build(), existingMovement._Etag); + await dbContext.Movements.Update(existingMovementBuilder.Build(), existingMovement._Etag); } } } diff --git a/Btms.Model/Cds/AlvsDecision.cs b/Btms.Model/Cds/AlvsDecision.cs index 2c9ba1d5..73b68c02 100644 --- a/Btms.Model/Cds/AlvsDecision.cs +++ b/Btms.Model/Cds/AlvsDecision.cs @@ -93,28 +93,44 @@ public class StatusChecker public class MovementStatus { + public const string NotLinkedStatus = "Not Linked"; + public const string LinkedStatus = "Linked"; + public const string InvestigateStatus = "Investigate"; + public static MovementStatus Default() { - return new MovementStatus() { ChedTypes = [] }; + return new MovementStatus() + { + ChedTypes = [], + Linked = false, + LinkStatus = NotLinkedStatus + }; } [Attr] [System.ComponentModel.Description("")] [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)] - public required ImportNotificationTypeEnum[]? ChedTypes { get; set; } + public required ImportNotificationTypeEnum[] ChedTypes { get; set; } [Attr] [System.ComponentModel.Description("")] - public string LinkStatus { get; set; } = "Not Linked"; + public required bool Linked { get; set; } + + [Attr] + [System.ComponentModel.Description("")] + public required string LinkStatus { get; set; } + + // [Attr] + // [System.ComponentModel.Description("")] + // public required string[] CountriesOfOrigin { get; set; } } + public partial class DecisionContext : IAuditContext // { - //TODO : Remove in favour of MovementStatus [Attr] [System.ComponentModel.Description("")] - [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)] - public ImportNotificationTypeEnum[]? ChedTypes { get; set; } + public List Checks { get; set; } = new List(); [Attr] [System.ComponentModel.Description("")] @@ -166,11 +182,6 @@ public partial class AlvsDecisionStatus // [Attr] [System.ComponentModel.Description("")] public DecisionContext Context { get; set; } = new DecisionContext(); - - // TODO - should we put the checks into context, and so into audit log? - [Attr] - [System.ComponentModel.Description("")] - public List Checks { get; set; } = new List(); } public partial class AlvsDecision // @@ -182,12 +193,6 @@ public partial class AlvsDecision // [Attr] [System.ComponentModel.Description("")] public required DecisionContext Context { get; set; } - - // TODO - should we put the checks into context, and so into audit log? - [Attr] - [System.ComponentModel.Description("")] - public required List Checks { get; set; } - } diff --git a/Btms.Model/Ipaffs/ImportNotification.cs b/Btms.Model/Ipaffs/ImportNotification.cs index c9ac2a02..f84111b1 100644 --- a/Btms.Model/Ipaffs/ImportNotification.cs +++ b/Btms.Model/Ipaffs/ImportNotification.cs @@ -28,7 +28,7 @@ public virtual string? Id get => ReferenceNumber!; set => ReferenceNumber = value; } - + [ChangeSetIgnore] // ReSharper disable once InconsistentNaming - want to use Mongo DB convention to indicate none core schema properties public string _Etag { get; set; } = default!; diff --git a/Btms.Model/Movement.cs b/Btms.Model/Movement.cs index f2896b54..005e41f0 100644 --- a/Btms.Model/Movement.cs +++ b/Btms.Model/Movement.cs @@ -24,7 +24,7 @@ public class Movement : IMongoIdentifiable, IDataEntity, IAuditable [ChangeSetIgnore] //TODO : should we ignore this or not? [Attr] - public required MovementStatus Status { get; set; } + public required MovementStatus BtmsStatus { get; set; } // This field is used by the jsonapi-consumer to control the correct casing in the type field [ChangeSetIgnore] diff --git a/Btms.Types.Ipaffs.Mapping.V1/ImportNotificationMapper.g.cs b/Btms.Types.Ipaffs.Mapping.V1/ImportNotificationMapper.g.cs index a12b8300..3880d259 100644 --- a/Btms.Types.Ipaffs.Mapping.V1/ImportNotificationMapper.g.cs +++ b/Btms.Types.Ipaffs.Mapping.V1/ImportNotificationMapper.g.cs @@ -10,6 +10,8 @@ #nullable enable +using Btms.Model.Ipaffs; + namespace Btms.Types.Ipaffs.Mapping; public static class ImportNotificationMapper @@ -22,6 +24,7 @@ public static Btms.Model.Ipaffs.ImportNotification Map(Btms.Types.Ipaffs.ImportN } var to = new Btms.Model.Ipaffs.ImportNotification(); + to.IpaffsId = from?.IpaffsId; to.Etag = from?.Etag; to.ExternalReferences = from?.ExternalReferences?.Select(x => ExternalReferenceMapper.Map(x)).ToArray(); diff --git a/BtmsBackend.sln b/BtmsBackend.sln index 2d35b648..ca99202c 100644 --- a/BtmsBackend.sln +++ b/BtmsBackend.sln @@ -67,6 +67,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Btms.Analytics.Tests", "Btm EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Btms.Metrics", "Btms.Metrics\Btms.Metrics.csproj", "{34731E9B-CF72-44B4-B73F-6921FD21A679}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestGenerator.IntegrationTesting.Backend", "TestGenerator.IntegrationTesting.Backend\TestGenerator.IntegrationTesting.Backend.csproj", "{A0212474-827F-4AE5-A086-F63B3F0C4DA0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -189,6 +191,10 @@ Global {34731E9B-CF72-44B4-B73F-6921FD21A679}.Debug|Any CPU.Build.0 = Debug|Any CPU {34731E9B-CF72-44B4-B73F-6921FD21A679}.Release|Any CPU.ActiveCfg = Release|Any CPU {34731E9B-CF72-44B4-B73F-6921FD21A679}.Release|Any CPU.Build.0 = Release|Any CPU + {A0212474-827F-4AE5-A086-F63B3F0C4DA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A0212474-827F-4AE5-A086-F63B3F0C4DA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A0212474-827F-4AE5-A086-F63B3F0C4DA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A0212474-827F-4AE5-A086-F63B3F0C4DA0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TestDataGenerator/ClearanceRequestBuilder.cs b/TestDataGenerator/ClearanceRequestBuilder.cs index fc6e4954..fa586c37 100644 --- a/TestDataGenerator/ClearanceRequestBuilder.cs +++ b/TestDataGenerator/ClearanceRequestBuilder.cs @@ -79,7 +79,7 @@ public ClearanceRequestBuilder WithCreationDate(DateTime entryDate, bool rand return Do(x => x.ServiceHeader!.ServiceCallTimestamp = entry); } - public ClearanceRequestBuilder WithEntryVersionNumber(int version) + public ClearanceRequestBuilder WithEntryVersionNumber(int version = 1) { return Do(x => { @@ -198,6 +198,7 @@ protected override ClearanceRequestBuilder Validate() return Do(cr => { cr.Header!.EntryReference.AssertHasValue("Clearance Request EntryReference missing"); + cr.Header!.EntryVersionNumber.AssertHasValue("Clearance Request EntryVersionNumber missing"); cr.Header!.DeclarationUcr.AssertHasValue("Clearance Request DeclarationUcr missing"); cr.Header!.MasterUcr.AssertHasValue("Clearance Request MasterUcr missing"); // cr.Header!.ArrivalDateTime.AssertHasValue("Clearance Request ArrivalDateTime missing"); diff --git a/TestDataGenerator/DecisionBuilder.cs b/TestDataGenerator/DecisionBuilder.cs index ed571fd9..e7879455 100644 --- a/TestDataGenerator/DecisionBuilder.cs +++ b/TestDataGenerator/DecisionBuilder.cs @@ -31,8 +31,11 @@ public static DecisionBuilder FromFile(string file) public DecisionBuilder WithReferenceNumber(string chedReference) { var id = MatchIdentifier.FromNotification(chedReference); - // - // base.Id = id.AsCdsEntryReference(); + return WithReferenceNumber(id); + } + + public DecisionBuilder WithReferenceNumber(MatchIdentifier id) + { return Do(x => { x.Header!.EntryReference = id.AsCdsEntryReference(); diff --git a/TestDataGenerator/Helpers/BuilderHelpers.cs b/TestDataGenerator/Helpers/BuilderHelpers.cs new file mode 100644 index 00000000..156a9124 --- /dev/null +++ b/TestDataGenerator/Helpers/BuilderHelpers.cs @@ -0,0 +1,34 @@ +using Btms.Types.Ipaffs; + +namespace TestDataGenerator.Helpers; + +public static class BuilderHelpers +{ + private static readonly string fullFolder = + $"{Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)}/Scenarios/Samples"; + + internal static ClearanceRequestBuilder GetClearanceRequestBuilder(string file, string fileExtension = ".json") + { + // return BuilderHelpers.GetClearanceRequestBuilder(file, fileExtension); + var fullPath = $"{fullFolder}/{file}{fileExtension}"; + var builder = new ClearanceRequestBuilder(fullPath); + + return builder; + } + + internal static DecisionBuilder GetDecisionBuilder(string file, string fileExtension = ".json") + { + var fullPath = $"{fullFolder}/{file}{fileExtension}"; + var builder = new DecisionBuilder(fullPath); + + return builder; + } + + internal static ImportNotificationBuilder GetNotificationBuilder(string file, string fileExtension = ".json") + { + var fullPath = $"{fullFolder}/{file}{fileExtension}"; + var builder = ImportNotificationBuilder.FromFile(fullPath); + + return builder; + } +} \ No newline at end of file diff --git a/TestDataGenerator/ScenarioGenerator.cs b/TestDataGenerator/ScenarioGenerator.cs index 8627e8c0..ac9f4b48 100644 --- a/TestDataGenerator/ScenarioGenerator.cs +++ b/TestDataGenerator/ScenarioGenerator.cs @@ -4,6 +4,7 @@ using Btms.Model; using Btms.Types.Alvs; using Btms.Types.Ipaffs; +using TestDataGenerator.Helpers; using TestDataGenerator.Scenarios; using Decision = Btms.Types.Alvs.Decision; @@ -16,27 +17,29 @@ public abstract class ScenarioGenerator public abstract GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config); + //TODO : remove these Get methods... internal ImportNotificationBuilder GetNotificationBuilder(string file, string fileExtension = ".json") { var fullPath = $"{_fullFolder}/{file}{fileExtension}"; var builder = ImportNotificationBuilder.FromFile(fullPath); - + return builder; } internal ClearanceRequestBuilder GetClearanceRequestBuilder(string file, string fileExtension = ".json") { - var fullPath = $"{_fullFolder}/{file}{fileExtension}"; - var builder = new ClearanceRequestBuilder(fullPath); - - return builder; + return BuilderHelpers.GetClearanceRequestBuilder(file, fileExtension); + // var fullPath = $"{_fullFolder}/{file}{fileExtension}"; + // var builder = new ClearanceRequestBuilder(fullPath); + // + // return builder; } - + internal DecisionBuilder GetDecisionBuilder(string file, string fileExtension = ".json") { var fullPath = $"{_fullFolder}/{file}{fileExtension}"; var builder = new DecisionBuilder(fullPath); - + return builder; } diff --git a/TestDataGenerator/Scenarios/CRNoMatch.cs b/TestDataGenerator/Scenarios/CRNoMatch.cs new file mode 100644 index 00000000..db0f13b4 --- /dev/null +++ b/TestDataGenerator/Scenarios/CRNoMatch.cs @@ -0,0 +1,135 @@ +using Btms.Common.Extensions; +using Btms.Model; +using Btms.Types.Alvs; +using Btms.Types.Ipaffs; +using Microsoft.Extensions.Logging; +using TestDataGenerator.Helpers; +using Decision = Btms.Types.Alvs.Decision; + +namespace TestDataGenerator.Scenarios; + +public static class NoMatchExtensions +{ + public static ClearanceRequestBuilder SimpleClearanceRequest(int scenario, int item, DateTime entryDate, ScenarioConfig config) + { + return BuilderHelpers.GetClearanceRequestBuilder("cr-one-item") + .WithCreationDate(entryDate) + .WithArrivalDateTimeOffset(DateTime.Today.ToDate(), DateTime.Now.ToTime()) + .WithReferenceNumberOneToOne(DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, + entryDate, item)) + .WithEntryVersionNumber(); + } + + public static ClearanceRequestBuilder WithTunaItem(this ClearanceRequestBuilder builder) + { + return builder + .WithItemNoChecks("N853", "16041421", "Tuna ROW CHEDP", 900); + } + + public static MatchIdentifier DocumentReferenceFromFirstDoc(this AlvsClearanceRequest clearanceRequest) + { + return MatchIdentifier.FromCds(clearanceRequest + .Items? + .First() + .Documents? + .First() + .DocumentReference!); + } + + public static DecisionBuilder GetDecisionBuilder( + this AlvsClearanceRequest clearanceRequest) + { + var reference = clearanceRequest + .DocumentReferenceFromFirstDoc(); + + // TODO - check with Matt what a sensible checkCode, decision & other fields we need to + // implement a 'real world' test here + var checkCode = "H2019"; + var decisionCode = "H01"; + + return BuilderHelpers.GetDecisionBuilder("decision-one-item") + .WithCreationDate(clearanceRequest.ServiceHeader!.ServiceCallTimestamp!.Value.AddHours(1), false) + .WithReferenceNumber(reference) + .WithEntryVersionNumber(1) + .WithDecisionVersionNumber() + .WithItemAndCheck(1, checkCode, decisionCode); + + } +} + +public class CrNoMatchSingleItemWithDecisionScenarioGenerator(ILogger logger) : ScenarioGenerator +{ + public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) + { + var clearanceRequest = NoMatchExtensions + .SimpleClearanceRequest(scenario, item, entryDate, config) + .WithTunaItem() + .WithDispatchCountryCode("FR") + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); + + var alvsDecision = clearanceRequest + .GetDecisionBuilder() + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", alvsDecision.Header!.EntryReference); + + return new GeneratorResult([clearanceRequest, alvsDecision]); + } +} +public class CrNoMatchNoChecksScenarioGenerator(ILogger logger) : ScenarioGenerator +{ + public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) + { + var clearanceRequest = NoMatchExtensions + .SimpleClearanceRequest(scenario, item, entryDate, config) + .WithTunaItem() + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); + + return new GeneratorResult([clearanceRequest]); + } +} + +public class CrNoMatchNoDecisionScenarioGenerator(ILogger logger) : ScenarioGenerator +{ + public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) + { + var reference = DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, entryDate, item); + + var clearanceRequest = NoMatchExtensions + .SimpleClearanceRequest(scenario, item, entryDate, config) + .WithReferenceNumberOneToOne(reference) + .WithRandomItems(10, 100) + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); + + return new GeneratorResult([clearanceRequest]); + } +} + +public class CrNoMatchScenarioGenerator(ILogger logger) : ScenarioGenerator +{ + public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) + { + // var reference = DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, entryDate, item); + + var clearanceRequest = NoMatchExtensions + .SimpleClearanceRequest(scenario, item, entryDate, config) + .WithRandomItems(10, 100) + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); + + var alvsDecision = clearanceRequest + .GetDecisionBuilder() + .ValidateAndBuild(); + + logger.LogInformation("Created {EntryReference}", alvsDecision.Header!.EntryReference); + + return new GeneratorResult([clearanceRequest, alvsDecision]); + } +} \ No newline at end of file diff --git a/TestDataGenerator/Scenarios/CRNoMatchNoChecksScenarioGenerator.cs b/TestDataGenerator/Scenarios/CRNoMatchNoChecksScenarioGenerator.cs deleted file mode 100644 index 65ca5f17..00000000 --- a/TestDataGenerator/Scenarios/CRNoMatchNoChecksScenarioGenerator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Btms.Common.Extensions; -using Btms.Types.Ipaffs; -using Microsoft.Extensions.Logging; -using TestDataGenerator.Helpers; - -namespace TestDataGenerator.Scenarios; - -public class CrNoMatchNoChecksScenarioGenerator(ILogger logger) : ScenarioGenerator -{ - public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) - { - var clearanceRequest = GetClearanceRequestBuilder("cr-one-item") - .WithCreationDate(entryDate) - .WithArrivalDateTimeOffset(DateTime.Today.ToDate(), DateTime.Now.ToTime()) - .WithReferenceNumberOneToOne(DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, entryDate, item)) - .WithItemNoChecks("N853", "16041421", "Tuna ROW CHEDP", 900) - .ValidateAndBuild(); - - logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); - - return new GeneratorResult([clearanceRequest]); - } -} \ No newline at end of file diff --git a/TestDataGenerator/Scenarios/CRNoMatchNoDecisionScenarioGenerator.cs b/TestDataGenerator/Scenarios/CRNoMatchNoDecisionScenarioGenerator.cs deleted file mode 100644 index df459305..00000000 --- a/TestDataGenerator/Scenarios/CRNoMatchNoDecisionScenarioGenerator.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Btms.Common.Extensions; -using Btms.Types.Ipaffs; -using Microsoft.Extensions.Logging; -using TestDataGenerator.Helpers; - -namespace TestDataGenerator.Scenarios; - -public class CrNoMatchNoDecisionScenarioGenerator(ILogger logger) : ScenarioGenerator -{ - public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) - { - var reference = DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, entryDate, item); - - var clearanceRequest = GetClearanceRequestBuilder("cr-one-item") - .WithCreationDate(entryDate) - .WithArrivalDateTimeOffset(DateTime.Today.ToDate(), DateTime.Now.ToTime()) - .WithReferenceNumberOneToOne(reference) - .WithRandomItems(10, 100) - .ValidateAndBuild(); - - logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); - - return new GeneratorResult([clearanceRequest]); - } -} \ No newline at end of file diff --git a/TestDataGenerator/Scenarios/CRNoMatchScenarioGenerator.cs b/TestDataGenerator/Scenarios/CRNoMatchScenarioGenerator.cs deleted file mode 100644 index b0f113e7..00000000 --- a/TestDataGenerator/Scenarios/CRNoMatchScenarioGenerator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Btms.Common.Extensions; -using Btms.Types.Ipaffs; -using Microsoft.Extensions.Logging; -using TestDataGenerator.Helpers; - -namespace TestDataGenerator.Scenarios; - -public class CrNoMatchScenarioGenerator(ILogger logger) : ScenarioGenerator -{ - public override GeneratorResult Generate(int scenario, int item, DateTime entryDate, ScenarioConfig config) - { - var reference = DataHelpers.GenerateReferenceNumber(ImportNotificationTypeEnum.Cveda, scenario, entryDate, item); - - var clearanceRequest = GetClearanceRequestBuilder("cr-one-item") - .WithCreationDate(entryDate) - .WithArrivalDateTimeOffset(DateTime.Today.ToDate(), DateTime.Now.ToTime()) - .WithReferenceNumberOneToOne(reference) - .WithRandomItems(10, 100) - .ValidateAndBuild(); - - logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); - - // TODO - check with Matt what a sensible checkCode, decision & other fields we need to - // implement a 'real world' test here - var checkCode = "H2019"; - var decisionCode = "H01"; - - var alvsDecision = GetDecisionBuilder("decision-one-item") - .WithCreationDate(clearanceRequest.ServiceHeader!.ServiceCallTimestamp!.Value.AddHours(1), false) - .WithReferenceNumber(reference) - .WithEntryVersionNumber(1) - .WithDecisionVersionNumber() - .WithItemAndCheck(1, checkCode, decisionCode) - .ValidateAndBuild(); - - logger.LogInformation("Created {EntryReference}", alvsDecision.Header!.EntryReference); - - return new GeneratorResult([clearanceRequest, alvsDecision]); - } -} \ No newline at end of file diff --git a/TestDataGenerator/Scenarios/ChedAManyCommoditiesScenarioGenerator.cs b/TestDataGenerator/Scenarios/ChedAManyCommoditiesScenarioGenerator.cs index b32d99f6..ef8fa22a 100644 --- a/TestDataGenerator/Scenarios/ChedAManyCommoditiesScenarioGenerator.cs +++ b/TestDataGenerator/Scenarios/ChedAManyCommoditiesScenarioGenerator.cs @@ -24,6 +24,7 @@ public override GeneratorResult Generate(int scenario, int item, DateTime entryD .WithCreationDate(entryDate) .WithArrivalDateTimeOffset(notification.PartOne!.ArrivalDate, notification.PartOne!.ArrivalTime) .WithReferenceNumberOneToOne(notification.ReferenceNumber!) + .WithEntryVersionNumber() .ValidateAndBuild(); logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); diff --git a/TestDataGenerator/Scenarios/ChedASimpleMatchScenarioGenerator.cs b/TestDataGenerator/Scenarios/ChedASimpleMatchScenarioGenerator.cs index dafb0bcf..e876e00a 100644 --- a/TestDataGenerator/Scenarios/ChedASimpleMatchScenarioGenerator.cs +++ b/TestDataGenerator/Scenarios/ChedASimpleMatchScenarioGenerator.cs @@ -22,6 +22,7 @@ public override GeneratorResult Generate(int scenario, int item, DateTime entryD .WithArrivalDateTimeOffset(notification.PartOne!.ArrivalDate, notification.PartOne!.ArrivalTime) .WithReferenceNumberOneToOne(notification.ReferenceNumber!) .WithDispatchCountryCode(notification.PartOne!.Route!.TransitingStates!.FirstOrDefault()) + .WithEntryVersionNumber() .ValidateAndBuild(); logger.LogInformation("Created {EntryReference}", clearanceRequest.Header!.EntryReference); diff --git a/TestGenerator.IntegrationTesting.Backend/BaseTest.cs b/TestGenerator.IntegrationTesting.Backend/BaseTest.cs new file mode 100644 index 00000000..8464d57c --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/BaseTest.cs @@ -0,0 +1,49 @@ +using TestDataGenerator; +using TestGenerator.IntegrationTesting.Backend.Fixtures; +using Xunit; +using Xunit.Abstractions; + +namespace TestGenerator.IntegrationTesting.Backend; + +public abstract class BaseTest : IClassFixture, IClassFixture + where T : ScenarioGenerator +{ + protected readonly BtmsClient Client; + protected readonly TestGeneratorFixture TestGeneratorFixture; + protected readonly BackendFixture BackendFixture; + // internal readonly BackendGeneratorFixture BackendGeneratorFixture; + protected readonly ITestOutputHelper TestOutputHelper; + + protected readonly List LoadedData; + protected BaseTest(ITestOutputHelper testOutputHelper, + // BackendGeneratorFixture backendGeneratorFixture + TestGeneratorFixture testGeneratorFixture, + BackendFixture backendFixture + ) + { + TestGeneratorFixture = testGeneratorFixture; + BackendFixture = backendFixture; + + // Client = backendGeneratorFixture.Backend.BtmsClient; + // TestGeneratorFixture = backendGeneratorFixture.TestGenerator; + // BackendFixture = backendGeneratorFixture.Backend; + TestOutputHelper = testOutputHelper; + + backendFixture.TestOutputHelper = testOutputHelper; + backendFixture.DatabaseName = GetType().Name; + backendFixture.Init(GetType().Name); + + Client = backendFixture.BtmsClient; + + var data = TestGeneratorFixture.GenerateTestData(); + LoadedData = BackendFixture + .LoadTestData(data) + .GetAwaiter() + .GetResult(); + } + + protected async Task ClearDb() + { + await Client.ClearDb(); + } +} \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/Helpers/BtmsClient.cs b/TestGenerator.IntegrationTesting.Backend/BtmsClient.cs similarity index 81% rename from Btms.Backend.IntegrationTests/Helpers/BtmsClient.cs rename to TestGenerator.IntegrationTesting.Backend/BtmsClient.cs index 8b32487f..3def5d2b 100644 --- a/Btms.Backend.IntegrationTests/Helpers/BtmsClient.cs +++ b/TestGenerator.IntegrationTesting.Backend/BtmsClient.cs @@ -5,13 +5,14 @@ using System.Text.Json; using System.Text.Json.Serialization; using Btms.Business.Commands; +using Btms.Model.Ipaffs; using Btms.SyncJob; using Elastic.CommonSchema; using FluentAssertions; using idunno.Authentication.Basic; using Xunit; -namespace Btms.Backend.IntegrationTests.Helpers; +namespace TestGenerator.IntegrationTesting.Backend.Fixtures; public class BtmsClient { @@ -111,11 +112,29 @@ public Task GetJob(string? jobId) return (response, Path.GetFileName(response.Headers.Location?.ToString())); } - public Task GetAnalyticsDashboard(string charts) + + public Task GetExceptions() { return client.GetAsync( - $"/analytics/dashboard?chartsToRender={charts}"); + $"/analytics/exceptions"); } + + public Task GetAnalyticsDashboard(string[] charts, + ImportNotificationTypeEnum[]? chedTypes = null, + string? country = null, + DateTime? dateFrom = null, + DateTime? dateTo = null) + { + var chartsFilter = String.Join("&chartsToRender=", charts); + var dateFromFilter = dateFrom.HasValue ? $"&dateFrom={dateFrom.Value:yyyy-MM-dd}" : ""; + var dateToFilter = dateTo.HasValue ? $"&dateTo={dateTo.Value:yyyy-MM-dd}" : ""; + var countryFilter = country != null ? $"&coo={country}" : ""; + var chedTypeFilter = chedTypes != null ? "&chedType=" + String.Join("&chedType=", chedTypes) : ""; + + return client.GetAsync( + $"/analytics/dashboard?chartsToRender={chartsFilter}{dateFromFilter}{dateToFilter}{countryFilter}{chedTypeFilter}"); + } + private async Task PostCommand(T command, string uri) { var jsonData = JsonSerializer.Serialize(command); diff --git a/TestGenerator.IntegrationTesting.Backend/Extensions/HttpExtensions.cs b/TestGenerator.IntegrationTesting.Backend/Extensions/HttpExtensions.cs new file mode 100644 index 00000000..d2f50314 --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Extensions/HttpExtensions.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Nodes; +using Btms.Common.Extensions; + +namespace TestGenerator.IntegrationTesting.Backend.Extensions; + +public static class HttpExtensions +{ + public static async Task GetString(this HttpResponseMessage? response) + { + var s = await response!.Content.ReadAsStringAsync(); + return s; + } + + public static async Task> ToJsonDictionary(this HttpResponseMessage? response) + { + var s = await response!.GetString(); + var responseDictionary = s.ToJsonDictionary(); + ArgumentNullException.ThrowIfNull(responseDictionary); + return responseDictionary; + } +} \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Extensions/JsonExtensions.cs b/TestGenerator.IntegrationTesting.Backend/Extensions/JsonExtensions.cs new file mode 100644 index 00000000..3f615098 --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Extensions/JsonExtensions.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Nodes; +using FluentAssertions; + +namespace TestGenerator.IntegrationTesting.Backend.Extensions; + +public static class JsonExtensions +{ + public static string[] GetKeys(this JsonNode node) + { + return node.AsObject() + .Select(x => x.As>().Key) + .ToArray(); + } +} \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs new file mode 100644 index 00000000..80d7a85d --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs @@ -0,0 +1,161 @@ +using Btms.Backend.Data; +using Btms.Backend.Data.Mongo; +using Btms.BlobService; +using Btms.Common.Extensions; +using Btms.Consumers.Extensions; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Driver; +using Serilog.Extensions.Logging; +using TestDataGenerator; +using Xunit.Abstractions; + +namespace TestGenerator.IntegrationTesting.Backend.Fixtures; + +public class BackendFixture +{ + private IMongoDbContext _mongoDbContext; + public BtmsClient BtmsClient; + + // public List LoadedData; + + // private IHost TestGeneratorApp { get; set; } + private BackendFactory WebApp { get; set; } + + public BackendFixture() + { + // Generate test data + + // var generatorBuilder = new HostBuilder(); + // generatorBuilder.ConfigureTestDataGenerator("Scenarios/Samples"); + + // var dbName = typeof(T).Name; + + } + + public void Init(string dbName) + { + WebApp = new BackendFactory(DatabaseName, TestOutputHelper); + (_mongoDbContext, BtmsClient) = WebApp.Start(); + } + + public ITestOutputHelper TestOutputHelper { get; set; } = null!; + public string DatabaseName { get; set; } = null!; + + // public IMongoDbContext GetDbContext() + // { + // return _mongoDbContext; + // } + + public async Task> LoadTestData(List testData) + { + await BtmsClient.ClearDb(); + + // var data = new List(); + + // TODO: Need a logger + var logger = NullLogger.Instance; + + await WebApp.Services.PushToConsumers(logger, testData.Select(d => d.Message)); + + // + // foreach (var t in testData) + // { + // + // + // // data.AddRange(t.GeneratorResult); + // // var output = t.GeneratorResult + // // .Select(r => new (generatorResult.Generator, 0, 1, 1, r)) + // // .ToList(); + // + // // LoadedData.AddRange(t.GeneratorResult); + // } + + + return testData; + } +} +public class BackendFactory(string databaseName, ITestOutputHelper testOutputHelper ) : WebApplicationFactory +{ + private IMongoDbContext? mongoDbContext; + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + // Any integration test overrides could be added here + // And we don't want to load the backend ini file + var configurationValues = new Dictionary + { + { "DisableLoadIniFile", "true" }, + { "BlobServiceOptions:CachePath", "Scenarios/Samples" }, + { "BlobServiceOptions:CacheReadEnabled", "true" }, + { "AuthKeyStore:Credentials:IntTest", "Password" } + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configurationValues!) + .Build(); + + builder + .UseConfiguration(configuration) + .ConfigureServices(services => + { + var mongoDatabaseDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(IMongoDatabase))!; + services.Remove(mongoDatabaseDescriptor); + + var blobOptionsValidatorDescriptor = services.SingleOrDefault(d => d.ServiceType == typeof(IValidateOptions))!; + services.Remove(blobOptionsValidatorDescriptor); + + services.AddSingleton(sp => + { + var options = sp.GetService>()!; + var settings = MongoClientSettings.FromConnectionString(options.Value.DatabaseUri); + var client = new MongoClient(settings); + + // _mongoDbContext = client + var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; + // convention must be registered before initialising collection + ConventionRegistry.Register("CamelCase", camelCaseConvention, _ => true); + + var dbName = string.IsNullOrEmpty(databaseName) ? + Random.Shared.Next().ToString() : + databaseName + .Replace("ScenarioGenerator", ""); + + var db = client.GetDatabase($"btms-{dbName}"); + + // TODO : Use our ILoggerFactory + mongoDbContext = new MongoDbContext(db, new SerilogLoggerFactory()); + return db; + }); + + if (testOutputHelper.HasValue()) + { + services.AddLogging(lb => lb.AddXUnit(testOutputHelper)); + } + }); + + builder.UseEnvironment("Development"); + } + + public (IMongoDbContext, BtmsClient) Start() + { + var builder = Host.CreateDefaultBuilder(); + + var host = base + .CreateHost(builder); + + // Creating the client causes the + var client = this.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); + var btmsClient = new BtmsClient(client); + + return (mongoDbContext!, btmsClient); + } + +} \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendGeneratorFixture.cs b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendGeneratorFixture.cs new file mode 100644 index 00000000..7c56337c --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendGeneratorFixture.cs @@ -0,0 +1,13 @@ +using TestDataGenerator; + +namespace TestGenerator.IntegrationTesting.Backend.Fixtures; + +public class BackendGeneratorFixture( + TestGeneratorFixture testGenerator, + BackendFixture backend +) + where T : ScenarioGenerator +{ + public TestGeneratorFixture TestGenerator { get; set; } = testGenerator; + public BackendFixture Backend { get; set; } = backend; +} \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Fixtures/IIntegrationTestsFixture.cs b/TestGenerator.IntegrationTesting.Backend/Fixtures/IIntegrationTestsFixture.cs new file mode 100644 index 00000000..e228c62c --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Fixtures/IIntegrationTestsFixture.cs @@ -0,0 +1,14 @@ +using Btms.Backend.Data; +using Microsoft.AspNetCore.Mvc.Testing; +using Xunit.Abstractions; + +namespace TestGenerator.IntegrationTesting.Backend.Fixtures; + +// public interface IIntegrationTestsFixture +// { +// ITestOutputHelper TestOutputHelper { get; set; } +// string DatabaseName { get; set; } +// +// BtmsClient CreateBtmsClient(WebApplicationFactoryClientOptions options); +// IMongoDbContext GetDbContext(); +// } \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Fixtures/TestGeneratorFixture.cs b/TestGenerator.IntegrationTesting.Backend/Fixtures/TestGeneratorFixture.cs new file mode 100644 index 00000000..d268bffc --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/Fixtures/TestGeneratorFixture.cs @@ -0,0 +1,65 @@ +using Btms.Backend.Data; +using Btms.Backend.Data.Mongo; +using Btms.BlobService; +using Btms.Common.Extensions; +using Btms.Consumers.Extensions; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using MongoDB.Bson.Serialization.Conventions; +using MongoDB.Driver; +using Serilog.Extensions.Logging; +using TestDataGenerator; +using TestDataGenerator.Extensions; +using TestDataGenerator.Scenarios; +using Xunit.Abstractions; + +namespace TestGenerator.IntegrationTesting.Backend.Fixtures; + +public class TestGeneratorFixture +{ + + + private IHost TestGeneratorApp { get; set; } + + public TestGeneratorFixture() + { + // Generate test data + + var generatorBuilder = new HostBuilder(); + generatorBuilder + .ConfigureTestDataGenerator("Scenarios/Samples"); + + TestGeneratorApp = generatorBuilder.Build(); + } + + public List GenerateTestData() where T : ScenarioGenerator + { + // TODO: Need a logger + var logger = NullLogger.Instance; + + var scenarioConfig = + TestGeneratorApp.Services.CreateScenarioConfig(1, 1, arrivalDateRange: 0); + + var generatorResults = scenarioConfig + .Generate(logger, 0); + + return generatorResults + .SelectMany(r => r.Select(m => new { Result = r, Message = m})) + .Select(rm => new GeneratedResult() + { + Count = 1, DateOffset = 1, Scenario = 1, + GeneratorResult = rm.Result, + Message = rm.Message + }) + // .Select(r => + // + // ) + .ToList(); + } +} \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/GeneratedResult.cs b/TestGenerator.IntegrationTesting.Backend/GeneratedResult.cs new file mode 100644 index 00000000..5ec13be6 --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/GeneratedResult.cs @@ -0,0 +1,12 @@ +using TestDataGenerator; + +namespace TestGenerator.IntegrationTesting.Backend; + +public class GeneratedResult +{ + public required ScenarioGenerator.GeneratorResult GeneratorResult { get; set; } + public required int Scenario { get; set; } + public required int DateOffset { get; set; } + public required int Count { get; set; } + public required object Message { get; set; } +} \ No newline at end of file diff --git a/Btms.Backend.IntegrationTests/JsonApiClient/JsonApiClient.cs b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiClient.cs similarity index 98% rename from Btms.Backend.IntegrationTests/JsonApiClient/JsonApiClient.cs rename to TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiClient.cs index b7b7ad01..d352f16c 100644 --- a/Btms.Backend.IntegrationTests/JsonApiClient/JsonApiClient.cs +++ b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiClient.cs @@ -6,7 +6,7 @@ using System.Text.Json; using JsonSerializer = System.Text.Json.JsonSerializer; -namespace Btms.Backend.IntegrationTests.JsonApiClient; +namespace TestGenerator.IntegrationTesting.Backend.JsonApiClient; public class JsonApiClient(HttpClient client) { diff --git a/Btms.Backend.IntegrationTests/JsonApiClient/JsonApiDocument.cs b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiDocument.cs similarity index 93% rename from Btms.Backend.IntegrationTests/JsonApiClient/JsonApiDocument.cs rename to TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiDocument.cs index 86bb0add..dd0d5ba5 100644 --- a/Btms.Backend.IntegrationTests/JsonApiClient/JsonApiDocument.cs +++ b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/JsonApiDocument.cs @@ -3,7 +3,7 @@ using JsonApiDotNetCore.Serialization.JsonConverters; using JsonApiDotNetCore.Serialization.Objects; -namespace Btms.Backend.IntegrationTests.JsonApiClient; +namespace TestGenerator.IntegrationTesting.Backend.JsonApiClient; public abstract class JsonApiDocument { diff --git a/Btms.Backend.IntegrationTests/JsonApiClient/ManyItemsJsonApiDocument.cs b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/ManyItemsJsonApiDocument.cs similarity index 85% rename from Btms.Backend.IntegrationTests/JsonApiClient/ManyItemsJsonApiDocument.cs rename to TestGenerator.IntegrationTesting.Backend/JsonApiClient/ManyItemsJsonApiDocument.cs index ae0b101d..c88e15a5 100644 --- a/Btms.Backend.IntegrationTests/JsonApiClient/ManyItemsJsonApiDocument.cs +++ b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/ManyItemsJsonApiDocument.cs @@ -1,7 +1,7 @@ using System.Text.Json; using JsonApiDotNetCore.Serialization.Objects; -namespace Btms.Backend.IntegrationTests.JsonApiClient; +namespace TestGenerator.IntegrationTesting.Backend.JsonApiClient; public class ManyItemsJsonApiDocument : JsonApiDocument> { diff --git a/Btms.Backend.IntegrationTests/JsonApiClient/Response.cs b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/Response.cs similarity index 82% rename from Btms.Backend.IntegrationTests/JsonApiClient/Response.cs rename to TestGenerator.IntegrationTesting.Backend/JsonApiClient/Response.cs index 1f628754..52431683 100644 --- a/Btms.Backend.IntegrationTests/JsonApiClient/Response.cs +++ b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/Response.cs @@ -1,7 +1,7 @@ using System.Net; using JsonApiSerializer.JsonApi; -namespace Btms.Backend.IntegrationTests.JsonApiClient; +namespace TestGenerator.IntegrationTesting.Backend.JsonApiClient; public class Response { diff --git a/Btms.Backend.IntegrationTests/JsonApiClient/SingleItemJsonApiDocument.cs b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/SingleItemJsonApiDocument.cs similarity index 83% rename from Btms.Backend.IntegrationTests/JsonApiClient/SingleItemJsonApiDocument.cs rename to TestGenerator.IntegrationTesting.Backend/JsonApiClient/SingleItemJsonApiDocument.cs index 5be7c475..652f616c 100644 --- a/Btms.Backend.IntegrationTests/JsonApiClient/SingleItemJsonApiDocument.cs +++ b/TestGenerator.IntegrationTesting.Backend/JsonApiClient/SingleItemJsonApiDocument.cs @@ -1,7 +1,7 @@ using System.Text.Json; using JsonApiDotNetCore.Serialization.Objects; -namespace Btms.Backend.IntegrationTests.JsonApiClient; +namespace TestGenerator.IntegrationTesting.Backend.JsonApiClient; public class SingleItemJsonApiDocument : JsonApiDocument { diff --git a/Btms.Backend.IntegrationTests/SyncJobResponse.cs b/TestGenerator.IntegrationTesting.Backend/SyncJobResponse.cs similarity index 91% rename from Btms.Backend.IntegrationTests/SyncJobResponse.cs rename to TestGenerator.IntegrationTesting.Backend/SyncJobResponse.cs index bcd17568..41f52cf1 100644 --- a/Btms.Backend.IntegrationTests/SyncJobResponse.cs +++ b/TestGenerator.IntegrationTesting.Backend/SyncJobResponse.cs @@ -1,6 +1,6 @@ using Btms.SyncJob; -namespace Btms.Backend.IntegrationTests; +namespace TestGenerator.IntegrationTesting.Backend; public class SyncJobResponse { diff --git a/TestGenerator.IntegrationTesting.Backend/TestGenerator.IntegrationTesting.Backend.csproj b/TestGenerator.IntegrationTesting.Backend/TestGenerator.IntegrationTesting.Backend.csproj new file mode 100644 index 00000000..3eed8c9f --- /dev/null +++ b/TestGenerator.IntegrationTesting.Backend/TestGenerator.IntegrationTesting.Backend.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + ..\..\..\..\..\..\..\usr\local\share\dotnet\shared\Microsoft.AspNetCore.App\8.0.6\Microsoft.AspNetCore.Hosting.Abstractions.dll + + + + + + + + + From b01aba85adc2c3fb101cb230a33dcac0075c975a Mon Sep 17 00:00:00 2001 From: Craig Edmunds Date: Fri, 3 Jan 2025 14:42:36 +0000 Subject: [PATCH 2/2] Finished refactoring of BaseTest class :fingers-crossed --- .../Fixtures/BasicSampleDataTestFixture.cs | 1 + .../Fixtures/MultiItemDataTestFixture.cs | 1 + .../MovementsByMaxVersionTests.cs | 4 +- .../ChedPDuplicateDecisionTests.cs | 4 +- .../DecisionTests/ChedPSimpleTests.cs | 4 +- .../NoMatchNoAlvsDecisionTests.cs | 4 +- .../DecisionTests/NoMatchTests.cs | 7 +-- .../BaseTest.cs | 26 ++++---- .../Extensions/TestOutputHelperExtensions.cs | 13 +++- .../Fixtures/BackendFixture.cs | 59 ++++--------------- 10 files changed, 46 insertions(+), 77 deletions(-) rename Btms.Analytics.Tests/Helpers/ITestOutputHelperExtensions.cs => TestGenerator.IntegrationTesting.Backend/Extensions/TestOutputHelperExtensions.cs (57%) diff --git a/Btms.Analytics.Tests/Fixtures/BasicSampleDataTestFixture.cs b/Btms.Analytics.Tests/Fixtures/BasicSampleDataTestFixture.cs index 15760199..86de9b59 100644 --- a/Btms.Analytics.Tests/Fixtures/BasicSampleDataTestFixture.cs +++ b/Btms.Analytics.Tests/Fixtures/BasicSampleDataTestFixture.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend.Extensions; using Xunit.Abstractions; namespace Btms.Analytics.Tests.Fixtures; diff --git a/Btms.Analytics.Tests/Fixtures/MultiItemDataTestFixture.cs b/Btms.Analytics.Tests/Fixtures/MultiItemDataTestFixture.cs index 87ce88a2..c22ba19f 100644 --- a/Btms.Analytics.Tests/Fixtures/MultiItemDataTestFixture.cs +++ b/Btms.Analytics.Tests/Fixtures/MultiItemDataTestFixture.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using TestDataGenerator.Scenarios; +using TestGenerator.IntegrationTesting.Backend.Extensions; using Xunit.Abstractions; namespace Btms.Analytics.Tests.Fixtures; diff --git a/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs b/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs index d3b9951f..aec68c84 100644 --- a/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs +++ b/Btms.Analytics.Tests/MovementsByMaxVersionTests.cs @@ -13,8 +13,8 @@ namespace Btms.Analytics.Tests; // public class MovementsByMaxVersionTests( // BasicSampleDataTestFixture basicSampleDataTestFixture, // ITestOutputHelper testOutputHelper) -public class MovementsByMaxVersionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) - : BaseTest(testOutputHelper, generatorFixture, backendFixture) +public class MovementsByMaxVersionTests(ITestOutputHelper output) + : BaseTest(output) { [Fact] diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs index 7c27e1e0..4d88ade8 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/ChedPDuplicateDecisionTests.cs @@ -12,8 +12,8 @@ namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class ChedPDuplicateDecisionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) - : BaseTest(testOutputHelper, generatorFixture, backendFixture) +public class ChedPDuplicateDecisionTests(ITestOutputHelper output) + : BaseTest(output) { // [Fact(Skip = "We currently import the duplicate alvs decision & store it on the movement")] [Fact] diff --git a/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs index a0a4eda6..863fe1f8 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/ChedPSimpleTests.cs @@ -13,8 +13,8 @@ namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class ChedPSimpleTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) - : BaseTest(testOutputHelper, generatorFixture, backendFixture) +public class ChedPSimpleTests(ITestOutputHelper output) + : BaseTest(output) { [Fact] diff --git a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs index 8cc64432..290defe3 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchNoAlvsDecisionTests.cs @@ -9,8 +9,8 @@ namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class NoMatchNoAlvsDecisionTests(ITestOutputHelper testOutputHelper, BackendFixture backendFixture, TestGeneratorFixture generatorFixture) - : BaseTest(testOutputHelper, generatorFixture, backendFixture)//, +public class NoMatchNoAlvsDecisionTests(ITestOutputHelper output) + : BaseTest(output) // IClassFixture>, // IClassFixture> { diff --git a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs index fd2a9e42..635df347 100644 --- a/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs +++ b/Btms.Backend.IntegrationTests/DecisionTests/NoMatchTests.cs @@ -10,11 +10,8 @@ namespace Btms.Backend.IntegrationTests.DecisionTests; [Trait("Category", "Integration")] -public class NoMatchTests(ITestOutputHelper testOutputHelper, - // BackendGeneratorFixture backendGeneratorFixture) - BackendFixture backendFixture, - TestGeneratorFixture generatorFixture) - : BaseTest(testOutputHelper, generatorFixture, backendFixture)//, +public class NoMatchTests(ITestOutputHelper output) + : BaseTest(output) ////IClassFixture>, ////IClassFixture> { diff --git a/TestGenerator.IntegrationTesting.Backend/BaseTest.cs b/TestGenerator.IntegrationTesting.Backend/BaseTest.cs index 8464d57c..9829350e 100644 --- a/TestGenerator.IntegrationTesting.Backend/BaseTest.cs +++ b/TestGenerator.IntegrationTesting.Backend/BaseTest.cs @@ -1,3 +1,4 @@ +using Microsoft.Extensions.DependencyInjection; using TestDataGenerator; using TestGenerator.IntegrationTesting.Backend.Fixtures; using Xunit; @@ -5,7 +6,7 @@ namespace TestGenerator.IntegrationTesting.Backend; -public abstract class BaseTest : IClassFixture, IClassFixture +public abstract class BaseTest // : IClassFixture, IClassFixture where T : ScenarioGenerator { protected readonly BtmsClient Client; @@ -15,25 +16,20 @@ public abstract class BaseTest : IClassFixture, IClassF protected readonly ITestOutputHelper TestOutputHelper; protected readonly List LoadedData; - protected BaseTest(ITestOutputHelper testOutputHelper, - // BackendGeneratorFixture backendGeneratorFixture - TestGeneratorFixture testGeneratorFixture, - BackendFixture backendFixture + protected BaseTest( + ITestOutputHelper testOutputHelper ) { - TestGeneratorFixture = testGeneratorFixture; - BackendFixture = backendFixture; - - // Client = backendGeneratorFixture.Backend.BtmsClient; - // TestGeneratorFixture = backendGeneratorFixture.TestGenerator; - // BackendFixture = backendGeneratorFixture.Backend; TestOutputHelper = testOutputHelper; - backendFixture.TestOutputHelper = testOutputHelper; - backendFixture.DatabaseName = GetType().Name; - backendFixture.Init(GetType().Name); + TestGeneratorFixture = new TestGeneratorFixture(); + BackendFixture = new BackendFixture(testOutputHelper, GetType().Name); + + // BackendFixture.TestOutputHelper = testOutputHelper; + // BackendFixture.DatabaseName = GetType().Name; + // BackendFixture.Init(GetType().Name); - Client = backendFixture.BtmsClient; + Client = BackendFixture.BtmsClient; var data = TestGeneratorFixture.GenerateTestData(); LoadedData = BackendFixture diff --git a/Btms.Analytics.Tests/Helpers/ITestOutputHelperExtensions.cs b/TestGenerator.IntegrationTesting.Backend/Extensions/TestOutputHelperExtensions.cs similarity index 57% rename from Btms.Analytics.Tests/Helpers/ITestOutputHelperExtensions.cs rename to TestGenerator.IntegrationTesting.Backend/Extensions/TestOutputHelperExtensions.cs index e495e103..7d75400b 100644 --- a/Btms.Analytics.Tests/Helpers/ITestOutputHelperExtensions.cs +++ b/TestGenerator.IntegrationTesting.Backend/Extensions/TestOutputHelperExtensions.cs @@ -2,15 +2,22 @@ using Microsoft.Extensions.Logging; using Xunit.Abstractions; -namespace Btms.Analytics.Tests.Helpers; +namespace TestGenerator.IntegrationTesting.Backend.Extensions; -public static class ITestOutputHelperExtensions +public static class TestOutputHelperExtensions { - public static ILogger GetLogger(this ITestOutputHelper helper) + public static ILoggerFactory GetLoggerFactory(this ITestOutputHelper helper) { var loggerProvider = new XUnitLoggerProvider(helper, new XUnitLoggerOptions()); var factory = new LoggerFactory([loggerProvider]); + return factory; + } + + public static ILogger GetLogger(this ITestOutputHelper helper) + { + var factory = helper.GetLoggerFactory(); + return factory.CreateLogger(); } } \ No newline at end of file diff --git a/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs index 80d7a85d..e5cbca80 100644 --- a/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs +++ b/TestGenerator.IntegrationTesting.Backend/Fixtures/BackendFixture.cs @@ -17,68 +17,36 @@ using TestDataGenerator; using Xunit.Abstractions; +using TestGenerator.IntegrationTesting.Backend.Extensions; + namespace TestGenerator.IntegrationTesting.Backend.Fixtures; public class BackendFixture { - private IMongoDbContext _mongoDbContext; - public BtmsClient BtmsClient; - - // public List LoadedData; + private readonly IMongoDbContext _mongoDbContext; + public readonly BtmsClient BtmsClient; - // private IHost TestGeneratorApp { get; set; } private BackendFactory WebApp { get; set; } - - public BackendFixture() - { - // Generate test data - - // var generatorBuilder = new HostBuilder(); - // generatorBuilder.ConfigureTestDataGenerator("Scenarios/Samples"); - - // var dbName = typeof(T).Name; - - } - public void Init(string dbName) + public readonly ITestOutputHelper TestOutputHelper; + + public BackendFixture(ITestOutputHelper testOutputHelper, string databaseName) { - WebApp = new BackendFactory(DatabaseName, TestOutputHelper); + TestOutputHelper = testOutputHelper; + + WebApp = new BackendFactory(databaseName, testOutputHelper); (_mongoDbContext, BtmsClient) = WebApp.Start(); + } - public ITestOutputHelper TestOutputHelper { get; set; } = null!; - public string DatabaseName { get; set; } = null!; - - // public IMongoDbContext GetDbContext() - // { - // return _mongoDbContext; - // } - public async Task> LoadTestData(List testData) { await BtmsClient.ClearDb(); - // var data = new List(); - - // TODO: Need a logger - var logger = NullLogger.Instance; + var logger = TestOutputHelper.GetLogger(); await WebApp.Services.PushToConsumers(logger, testData.Select(d => d.Message)); - // - // foreach (var t in testData) - // { - // - // - // // data.AddRange(t.GeneratorResult); - // // var output = t.GeneratorResult - // // .Select(r => new (generatorResult.Generator, 0, 1, 1, r)) - // // .ToList(); - // - // // LoadedData.AddRange(t.GeneratorResult); - // } - - return testData; } } @@ -130,8 +98,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) var db = client.GetDatabase($"btms-{dbName}"); - // TODO : Use our ILoggerFactory - mongoDbContext = new MongoDbContext(db, new SerilogLoggerFactory()); + mongoDbContext = new MongoDbContext(db, testOutputHelper.GetLoggerFactory()); return db; });