diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Common/Events/EventBus/InMemory/InMemoryEventBusTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Common/Events/EventBus/InMemory/InMemoryEventBusTests.cs index 8461d0c9..5b2226e5 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Common/Events/EventBus/InMemory/InMemoryEventBusTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Common/Events/EventBus/InMemory/InMemoryEventBusTests.cs @@ -27,7 +27,7 @@ internal async Task Given_valid_event_published_Then_event_should_be_consumed() private IEventBus GetEventBus() => _applicationInMemory.Services - .CreateScope() + .CreateScope()! .ServiceProvider .GetRequiredService(); } diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/PrepareContract/PrepareContractTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/PrepareContract/PrepareContractTests.cs index e5e11837..636a52d6 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/PrepareContract/PrepareContractTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/PrepareContract/PrepareContractTests.cs @@ -11,7 +11,7 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Contracts.PrepareCont public sealed class PrepareContractTests( WebApplicationFactory applicationInMemoryFactory, DatabaseContainer database) : IClassFixture>, - IClassFixture + IClassFixture, IAsyncLifetime { private readonly HttpClient _applicationHttpClient = applicationInMemoryFactory .WithContainerDatabaseConfigured(database.ConnectionString!) @@ -24,7 +24,7 @@ internal async Task Given_valid_contract_preparation_request_Then_should_return_ var requestParameters = PrepareContractRequestParameters.GetValid(); // Act - var prepareContractResponse = await PrepareCorrectContract(requestParameters); + using var prepareContractResponse = await PrepareCorrectContract(requestParameters); // Assert prepareContractResponse.StatusCode.ShouldBe(HttpStatusCode.Created); @@ -61,7 +61,7 @@ internal async Task Given_contract_preparation_request_with_invalid_age_Then_sho requestParameters.MaxAge, requestParameters.MinHeight, requestParameters.MaxHeight); // Act - var prepareContractResponse = + using var prepareContractResponse = await _applicationHttpClient.PostAsJsonAsync(ContractsApiPaths.Prepare, prepareContractRequest); // Assert @@ -82,7 +82,7 @@ internal async Task Given_contract_preparation_request_with_invalid_height_Then_ requestParameters.MaxAge, requestParameters.MinHeight, requestParameters.MaxHeight); // Act - var prepareContractResponse = + using var prepareContractResponse = await _applicationHttpClient.PostAsJsonAsync(ContractsApiPaths.Prepare, prepareContractRequest); // Assert @@ -103,7 +103,7 @@ internal async Task await PrepareCorrectContract(requestParameters, customerId); //Act - var prepareContractResponse = await PrepareCorrectContract(requestParameters, customerId); + using var prepareContractResponse = await PrepareCorrectContract(requestParameters, customerId); // Assert prepareContractResponse.StatusCode.ShouldBe(HttpStatusCode.Conflict); @@ -122,4 +122,12 @@ private async Task PrepareCorrectContract(PrepareContractRe return prepareContractResponse; } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _applicationHttpClient.Dispose(); + await applicationInMemoryFactory.DisposeAsync(); + } } diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/SignContract/SignContractTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/SignContract/SignContractTests.cs index d7c1ceea..53b58014 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/SignContract/SignContractTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Contracts/SignContract/SignContractTests.cs @@ -9,17 +9,29 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Contracts.SignContrac using EvolutionaryArchitecture.Fitnet.Common.Events.EventBus; using Microsoft.AspNetCore.Mvc; -public sealed class SignContractTests : IClassFixture>, IClassFixture +public sealed class SignContractTests : IClassFixture>, IClassFixture, IAsyncLifetime { private readonly HttpClient _applicationHttpClient; private readonly IEventBus _fakeEventBus = Substitute.For(); + private readonly WebApplicationFactory _applicationInMemoryFactory; public SignContractTests(WebApplicationFactory applicationInMemoryFactory, - DatabaseContainer database) => + DatabaseContainer database) + { + _applicationInMemoryFactory = applicationInMemoryFactory; _applicationHttpClient = applicationInMemoryFactory .WithFakeEventBus(_fakeEventBus) .WithContainerDatabaseConfigured(database.ConnectionString!) .CreateClient(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _applicationHttpClient.Dispose(); + await _applicationInMemoryFactory.DisposeAsync(); + } [Fact] internal async Task Given_valid_contract_signature_request_Then_should_return_no_content_status_code() @@ -30,7 +42,7 @@ internal async Task Given_valid_contract_signature_request_Then_should_return_no var signContractRequest = new SignContractRequest(requestParameters.SignedAt); // Act - var signContractResponse = + using var signContractResponse = await _applicationHttpClient.PatchAsJsonAsync(requestParameters.Url, signContractRequest); // Assert @@ -63,7 +75,7 @@ internal async Task Given_contract_signature_request_with_not_existing_id_Then_s var signContractRequest = new SignContractRequest(requestParameters.SignedAt); // Act - var signContractResponse = + using var signContractResponse = await _applicationHttpClient.PatchAsJsonAsync(requestParameters.Url, signContractRequest); // Assert @@ -81,7 +93,7 @@ internal async Task var signContractRequest = new SignContractRequest(requestParameters.SignedAt); // Act - var signContractResponse = + using var signContractResponse = await _applicationHttpClient.PatchAsJsonAsync(requestParameters.Url, signContractRequest); // Assert @@ -97,7 +109,7 @@ private async Task PrepareContract() var requestParameters = PrepareContractRequestParameters.GetValid(); PrepareContractRequest prepareContractRequest = new PrepareContractRequestFaker(requestParameters.MinAge, requestParameters.MaxAge, requestParameters.MinHeight, requestParameters.MaxHeight); - var prepareContractResponse = + using var prepareContractResponse = await _applicationHttpClient.PostAsJsonAsync(ContractsApiPaths.Prepare, prepareContractRequest); var preparedContractId = await prepareContractResponse.Content.ReadFromJsonAsync(); diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Offers/Prepare/PrepareOfferTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Offers/Prepare/PrepareOfferTests.cs index 2143a2cd..c85a4b5b 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Offers/Prepare/PrepareOfferTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Offers/Prepare/PrepareOfferTests.cs @@ -19,7 +19,6 @@ public PrepareOfferTests(WebApplicationFactory applicationInMemoryFacto _applicationInMemory = applicationInMemoryFactory .WithFakeEventBus(_fakeEventBus) .WithContainerDatabaseConfigured(database.ConnectionString!); - _applicationInMemory.CreateClient(); } @@ -41,4 +40,4 @@ internal async Task Given_pass_expired_event_published_Then_new_offer_should_be_ private void EnsureThatOfferPreparedEventWasPublished() => _fakeEventBus.Received(1) .PublishAsync(Arg.Any(), Arg.Any()); -} \ No newline at end of file +} diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/MarkPassAsExpired/MarkPassAsExpiredTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/MarkPassAsExpired/MarkPassAsExpiredTests.cs index 62d0d2b6..af61f34e 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/MarkPassAsExpired/MarkPassAsExpiredTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/MarkPassAsExpired/MarkPassAsExpiredTests.cs @@ -10,7 +10,7 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Passes.MarkPassAsExpi using Fitnet.Passes.MarkPassAsExpired.Events; public sealed class MarkPassAsExpiredTests : IClassFixture>, - IClassFixture + IClassFixture, IAsyncLifetime { private static readonly StringContent EmptyContent = new(string.Empty); @@ -51,7 +51,7 @@ internal async Task Given_valid_mark_pass_as_expired_request_Then_should_publish var url = BuildUrl(registeredPassId); // Act - var markAsExpiredResponse = await _applicationHttpClient.PatchAsJsonAsync(url, EmptyContent); + using var markAsExpiredResponse = await _applicationHttpClient.PatchAsJsonAsync(url, EmptyContent); // Assert markAsExpiredResponse.StatusCode.ShouldBe(HttpStatusCode.NoContent); @@ -65,7 +65,7 @@ internal async Task Given_mark_pass_as_expired_request_with_not_existing_id_Then var url = BuildUrl(notExistingId); // Act - var markAsExpiredResponse = await _applicationHttpClient.PatchAsJsonAsync(url, EmptyContent); + using var markAsExpiredResponse = await _applicationHttpClient.PatchAsJsonAsync(url, EmptyContent); // Assert markAsExpiredResponse.StatusCode.ShouldBe(HttpStatusCode.NotFound); @@ -91,9 +91,10 @@ private async Task GetCreatedPass(Guid customerId) private async Task CreatedPass(Guid customerId) { - var getAllPassesResponse = await _applicationHttpClient.GetAsync(PassesApiPaths.GetAll); + using var getAllPassesResponse = await _applicationHttpClient.GetAsync(PassesApiPaths.GetAll); var response = await getAllPassesResponse.Content.ReadFromJsonAsync(); var createdPass = response!.Passes.FirstOrDefault(pass => pass.CustomerId == customerId); + return createdPass; } @@ -101,4 +102,12 @@ private async Task GetCreatedPass(Guid customerId) private void EnsureThatPassExpiredEventWasPublished() => _fakeEventBus.Received(1) .PublishAsync(Arg.Any(), Arg.Any()); + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _applicationHttpClient.Dispose(); + await _applicationInMemoryFactory.DisposeAsync(); + } } diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/RegisterPass/RegisterPassTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/RegisterPass/RegisterPassTests.cs index df01bcb9..71e0ed1a 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/RegisterPass/RegisterPassTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Passes/RegisterPass/RegisterPassTests.cs @@ -6,19 +6,27 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Passes.RegisterPass; using Fitnet.Passes.RegisterPass.Events; using EvolutionaryArchitecture.Fitnet.Common.Events.EventBus; -public sealed class RegisterPassTests : IClassFixture>, - IClassFixture +public sealed class RegisterPassTests : IClassFixture>, IClassFixture, IAsyncLifetime { private readonly WebApplicationFactory _applicationInMemory; private readonly IEventBus _fakeEventBus = Substitute.For(); + private readonly HttpClient _applicationHttpClient; public RegisterPassTests(WebApplicationFactory applicationInMemoryFactory, DatabaseContainer database) { _applicationInMemory = applicationInMemoryFactory - .WithContainerDatabaseConfigured(database.ConnectionString!) - .WithFakeEventBus(_fakeEventBus); - _applicationInMemory.CreateClient(); + .WithContainerDatabaseConfigured(database.ConnectionString!) + .WithFakeEventBus(_fakeEventBus); + _applicationHttpClient = _applicationInMemory.CreateClient(); + } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _applicationHttpClient.Dispose(); + await _applicationInMemory.DisposeAsync(); } [Fact] diff --git a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Reports/GenerateNewPassesPerMonthReport/GenerateNewPassesPerMonthReportTests.cs b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Reports/GenerateNewPassesPerMonthReport/GenerateNewPassesPerMonthReportTests.cs index 41ae1d64..99bc0655 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Reports/GenerateNewPassesPerMonthReport/GenerateNewPassesPerMonthReportTests.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet.IntegrationTests/Reports/GenerateNewPassesPerMonthReport/GenerateNewPassesPerMonthReportTests.cs @@ -1,5 +1,6 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Reports.GenerateNewPassesPerMonthReport; +using System; using Common.TestEngine.Configuration; using Common.TestEngine.IntegrationEvents.Handlers; using Common.TestEngine.Time; @@ -9,7 +10,7 @@ namespace EvolutionaryArchitecture.Fitnet.IntegrationTests.Reports.GenerateNewPa using Passes.RegisterPass; using TestData; -public sealed class GenerateNewPassesPerMonthReportTests : IClassFixture>, IClassFixture +public sealed class GenerateNewPassesPerMonthReportTests : IClassFixture>, IClassFixture, IAsyncLifetime { private static readonly FakeTimeProvider FakeTimeProvider = new(ReportTestCases.FakeNowDate); private readonly HttpClient _applicationHttpClient; @@ -21,7 +22,6 @@ public GenerateNewPassesPerMonthReportTests(WebApplicationFactory appli _applicationInMemoryFactory = applicationInMemoryFactory .WithContainerDatabaseConfigured(database.ConnectionString!) .WithTime(FakeTimeProvider); - _applicationHttpClient = _applicationInMemoryFactory.CreateClient(); } @@ -34,7 +34,7 @@ internal async Task Given_valid_generate_new_report_request_Then_should_return_c await RegisterPasses(passRegistrationDateRanges); // Act - var getReportResult = await _applicationHttpClient.GetAsync(ReportsApiPaths.GenerateNewReport); + using var getReportResult = await _applicationHttpClient.GetAsync(ReportsApiPaths.GenerateNewReport); // Assert getReportResult.StatusCode.ShouldBe(HttpStatusCode.OK); @@ -58,4 +58,12 @@ private async Task RegisterPass(DateTimeOffset from, DateTimeOffset to) var @event = ContractSignedEventFaker.Create(from, to); await integrationEventHandler.Handle(@event, CancellationToken.None); } + + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + _applicationHttpClient.Dispose(); + await _applicationInMemoryFactory.DisposeAsync(); + } } diff --git a/Chapter-1-initial-architecture/Src/Fitnet/Program.cs b/Chapter-1-initial-architecture/Src/Fitnet/Program.cs index fe6f6c01..5032cf67 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet/Program.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet/Program.cs @@ -23,7 +23,7 @@ builder.Services.AddOffers(builder.Configuration); builder.Services.AddReports(); -var app = builder.Build(); +await using var app = builder.Build(); if (app.Environment.IsDevelopment()) { diff --git a/Chapter-1-initial-architecture/Src/Fitnet/Reports/DataAccess/DatabaseConnectionFactory.cs b/Chapter-1-initial-architecture/Src/Fitnet/Reports/DataAccess/DatabaseConnectionFactory.cs index 855c4ee8..eca7f65f 100644 --- a/Chapter-1-initial-architecture/Src/Fitnet/Reports/DataAccess/DatabaseConnectionFactory.cs +++ b/Chapter-1-initial-architecture/Src/Fitnet/Reports/DataAccess/DatabaseConnectionFactory.cs @@ -13,7 +13,6 @@ public IDbConnection Create() { return _connection; } - _connection = new NpgsqlConnection(configuration.GetConnectionString("Reports")); _connection.Open();