diff --git a/src/Services/Booking/tests/IntegrationTest/CustomWebApplicationFactory.cs b/src/Services/Booking/tests/IntegrationTest/CustomWebApplicationFactory.cs deleted file mode 100644 index fcd1a13..0000000 --- a/src/Services/Booking/tests/IntegrationTest/CustomWebApplicationFactory.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using BuildingBlocks.MassTransit; -using BuildingBlocks.Web; -using MassTransit; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using NSubstitute; -using Respawn; - -namespace Integration.Test; - -public class CustomWebApplicationFactory : WebApplicationFactory -{ - public Checkpoint Checkpoint { get; set; } - public IConfiguration Configuration => Services.GetRequiredService(); - public Action? TestRegistrationServices { get; set; } - - protected override void ConfigureWebHost(IWebHostBuilder builder) - { - //https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests#set-the-environment - //https://stackoverflow.com/questions/43927955/should-getenvironmentvariable-work-in-xunit-test/43951218 - - //we could read env from our test launch setting or we can set it directly here - builder.UseEnvironment("test"); - - //The test app's builder.ConfigureTestServices callback is executed after the app's Startup.ConfigureServices code is executed. - builder.ConfigureTestServices(services => - { - services.RemoveAll(typeof(IHostedService)); - services.ReplaceSingleton(AddHttpContextAccessorMock); - TestRegistrationServices?.Invoke(services); - services.AddMassTransitTestHarness(x => - { - x.UsingRabbitMq((context, cfg) => - { - var rabbitMqOptions = services.GetOptions("RabbitMq"); - var host = rabbitMqOptions.HostName; - - cfg.Host(host, h => - { - h.Username(rabbitMqOptions.UserName); - h.Password(rabbitMqOptions.Password); - }); - cfg.ConfigureEndpoints(context); - }); - }); - - Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; - - TestRegistrationServices?.Invoke(services); - }); - } - - private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) - { - var httpContextAccessorMock = Substitute.For(); - using var scope = serviceProvider.CreateScope(); - httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; - - httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); - httpContextAccessorMock.HttpContext.Request.Scheme = "http"; - - return httpContextAccessorMock; - } -} diff --git a/src/Services/Booking/tests/IntegrationTest/IntegrationTestFixture.cs b/src/Services/Booking/tests/IntegrationTest/IntegrationTestFixture.cs index bd35dfd..30213ce 100644 --- a/src/Services/Booking/tests/IntegrationTest/IntegrationTestFixture.cs +++ b/src/Services/Booking/tests/IntegrationTest/IntegrationTestFixture.cs @@ -3,11 +3,21 @@ using System.Net.Http; using System.Threading.Tasks; using Booking.Data; using BuildingBlocks.Domain.Model; +using BuildingBlocks.MassTransit; +using BuildingBlocks.Web; using Grpc.Net.Client; +using MassTransit; using MassTransit.Testing; using MediatR; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; +using NSubstitute; +using Respawn; using Serilog; using Xunit; using Xunit.Abstractions; @@ -21,29 +31,55 @@ public class FixtureCollection : ICollectionFixture public class IntegrationTestFixture : IAsyncLifetime { - private readonly CustomWebApplicationFactory _factory; - - public IntegrationTestFixture() - { - // Ref: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#basic-tests-with-the-default-webapplicationfactory - _factory = new CustomWebApplicationFactory(); - } - + private WebApplicationFactory _factory; + public Checkpoint Checkpoint { get; set; } + public Action? TestRegistrationServices { get; set; } public IServiceProvider ServiceProvider => _factory.Services; - public IConfiguration Configuration => _factory.Configuration; + public IConfiguration Configuration => _factory.Services.GetRequiredService(); public HttpClient HttpClient => _factory.CreateClient(); public ITestHarness TestHarness => CreateHarness(); public GrpcChannel Channel => CreateChannel(); public virtual Task InitializeAsync() { + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.UseEnvironment("test"); + builder.ConfigureServices(services => + { + services.RemoveAll(typeof(IHostedService)); + services.ReplaceSingleton(AddHttpContextAccessorMock); + TestRegistrationServices?.Invoke(services); + services.AddMassTransitTestHarness(x => + { + x.UsingRabbitMq((context, cfg) => + { + var rabbitMqOptions = services.GetOptions("RabbitMq"); + var host = rabbitMqOptions.HostName; + + cfg.Host(host, h => + { + h.Username(rabbitMqOptions.UserName); + h.Password(rabbitMqOptions.Password); + }); + cfg.ConfigureEndpoints(context); + }); + }); + + Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + + TestRegistrationServices?.Invoke(services); + }); + }); + return Task.CompletedTask; } public virtual async Task DisposeAsync() { if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) - await _factory.Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); + await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _factory.DisposeAsync(); } @@ -61,7 +97,7 @@ public class IntegrationTestFixture : IAsyncLifetime public void RegisterTestServices(Action services) { - _factory.TestRegistrationServices = services; + TestRegistrationServices = services; } public async Task ExecuteScopeAsync(Func action) @@ -212,4 +248,16 @@ public class IntegrationTestFixture : IAsyncLifetime { return GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient}); } + + private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) + { + var httpContextAccessorMock = Substitute.For(); + using var scope = serviceProvider.CreateScope(); + httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; + + httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); + httpContextAccessorMock.HttpContext.Request.Scheme = "http"; + + return httpContextAccessorMock; + } } diff --git a/src/Services/Flight/tests/IntegrationTest/CustomWebApplicationFactory.cs b/src/Services/Flight/tests/IntegrationTest/CustomWebApplicationFactory.cs deleted file mode 100644 index fcd1a13..0000000 --- a/src/Services/Flight/tests/IntegrationTest/CustomWebApplicationFactory.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using BuildingBlocks.MassTransit; -using BuildingBlocks.Web; -using MassTransit; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using NSubstitute; -using Respawn; - -namespace Integration.Test; - -public class CustomWebApplicationFactory : WebApplicationFactory -{ - public Checkpoint Checkpoint { get; set; } - public IConfiguration Configuration => Services.GetRequiredService(); - public Action? TestRegistrationServices { get; set; } - - protected override void ConfigureWebHost(IWebHostBuilder builder) - { - //https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests#set-the-environment - //https://stackoverflow.com/questions/43927955/should-getenvironmentvariable-work-in-xunit-test/43951218 - - //we could read env from our test launch setting or we can set it directly here - builder.UseEnvironment("test"); - - //The test app's builder.ConfigureTestServices callback is executed after the app's Startup.ConfigureServices code is executed. - builder.ConfigureTestServices(services => - { - services.RemoveAll(typeof(IHostedService)); - services.ReplaceSingleton(AddHttpContextAccessorMock); - TestRegistrationServices?.Invoke(services); - services.AddMassTransitTestHarness(x => - { - x.UsingRabbitMq((context, cfg) => - { - var rabbitMqOptions = services.GetOptions("RabbitMq"); - var host = rabbitMqOptions.HostName; - - cfg.Host(host, h => - { - h.Username(rabbitMqOptions.UserName); - h.Password(rabbitMqOptions.Password); - }); - cfg.ConfigureEndpoints(context); - }); - }); - - Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; - - TestRegistrationServices?.Invoke(services); - }); - } - - private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) - { - var httpContextAccessorMock = Substitute.For(); - using var scope = serviceProvider.CreateScope(); - httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; - - httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); - httpContextAccessorMock.HttpContext.Request.Scheme = "http"; - - return httpContextAccessorMock; - } -} diff --git a/src/Services/Flight/tests/IntegrationTest/IntegrationTestFixture.cs b/src/Services/Flight/tests/IntegrationTest/IntegrationTestFixture.cs index 65e1064..8a57d30 100644 --- a/src/Services/Flight/tests/IntegrationTest/IntegrationTestFixture.cs +++ b/src/Services/Flight/tests/IntegrationTest/IntegrationTestFixture.cs @@ -3,15 +3,24 @@ using System.Net.Http; using System.Threading.Tasks; using BuildingBlocks.Domain.Model; using BuildingBlocks.EFCore; +using BuildingBlocks.MassTransit; +using BuildingBlocks.Web; using Flight.Data; +using FluentAssertions.Common; using Grpc.Net.Client; +using MassTransit; using MassTransit.Testing; using MediatR; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; using NSubstitute; +using Respawn; using Serilog; using Xunit; using Xunit.Abstractions; @@ -19,20 +28,17 @@ using Xunit.Abstractions; namespace Integration.Test; [CollectionDefinition(nameof(IntegrationTestFixture))] -public class FixtureCollection : ICollectionFixture { } +public class FixtureCollection : ICollectionFixture +{ +} public class IntegrationTestFixture : IAsyncLifetime { - private readonly CustomWebApplicationFactory _factory; - - public IntegrationTestFixture() - { - // Ref: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#basic-tests-with-the-default-webapplicationfactory - _factory = new CustomWebApplicationFactory(); - } - + private WebApplicationFactory _factory; + public Checkpoint Checkpoint { get; set; } + public Action? TestRegistrationServices { get; set; } public IServiceProvider ServiceProvider => _factory.Services; - public IConfiguration Configuration => _factory.Configuration; + public IConfiguration Configuration => _factory.Services.GetRequiredService(); public HttpClient HttpClient => _factory.CreateClient(); public ITestHarness TestHarness => CreateHarness(); public GrpcChannel Channel => CreateChannel(); @@ -50,17 +56,48 @@ public class IntegrationTestFixture : IAsyncLifetime return null; } - public void RegisterTestServices(Action services) => _factory.TestRegistrationServices = services; + public void RegisterTestServices(Action services) => TestRegistrationServices = services; public virtual Task InitializeAsync() { + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.UseEnvironment("test"); + builder.ConfigureServices(services => + { + services.RemoveAll(typeof(IHostedService)); + services.ReplaceSingleton(AddHttpContextAccessorMock); + TestRegistrationServices?.Invoke(services); + services.AddMassTransitTestHarness(x => + { + x.UsingRabbitMq((context, cfg) => + { + var rabbitMqOptions = services.GetOptions("RabbitMq"); + var host = rabbitMqOptions.HostName; + + cfg.Host(host, h => + { + h.Username(rabbitMqOptions.UserName); + h.Password(rabbitMqOptions.Password); + }); + cfg.ConfigureEndpoints(context); + }); + }); + + Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + + TestRegistrationServices?.Invoke(services); + }); + }); + return Task.CompletedTask; } public virtual async Task DisposeAsync() { if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) - await _factory.Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); + await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _factory.DisposeAsync(); } @@ -213,4 +250,16 @@ public class IntegrationTestFixture : IAsyncLifetime { return GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient}); } + + private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) + { + var httpContextAccessorMock = Substitute.For(); + using var scope = serviceProvider.CreateScope(); + httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; + + httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); + httpContextAccessorMock.HttpContext.Request.Scheme = "http"; + + return httpContextAccessorMock; + } } diff --git a/src/Services/Identity/tests/IntegrationTest/CustomWebApplicationFactory.cs b/src/Services/Identity/tests/IntegrationTest/CustomWebApplicationFactory.cs deleted file mode 100644 index fcd1a13..0000000 --- a/src/Services/Identity/tests/IntegrationTest/CustomWebApplicationFactory.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using BuildingBlocks.MassTransit; -using BuildingBlocks.Web; -using MassTransit; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using NSubstitute; -using Respawn; - -namespace Integration.Test; - -public class CustomWebApplicationFactory : WebApplicationFactory -{ - public Checkpoint Checkpoint { get; set; } - public IConfiguration Configuration => Services.GetRequiredService(); - public Action? TestRegistrationServices { get; set; } - - protected override void ConfigureWebHost(IWebHostBuilder builder) - { - //https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests#set-the-environment - //https://stackoverflow.com/questions/43927955/should-getenvironmentvariable-work-in-xunit-test/43951218 - - //we could read env from our test launch setting or we can set it directly here - builder.UseEnvironment("test"); - - //The test app's builder.ConfigureTestServices callback is executed after the app's Startup.ConfigureServices code is executed. - builder.ConfigureTestServices(services => - { - services.RemoveAll(typeof(IHostedService)); - services.ReplaceSingleton(AddHttpContextAccessorMock); - TestRegistrationServices?.Invoke(services); - services.AddMassTransitTestHarness(x => - { - x.UsingRabbitMq((context, cfg) => - { - var rabbitMqOptions = services.GetOptions("RabbitMq"); - var host = rabbitMqOptions.HostName; - - cfg.Host(host, h => - { - h.Username(rabbitMqOptions.UserName); - h.Password(rabbitMqOptions.Password); - }); - cfg.ConfigureEndpoints(context); - }); - }); - - Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; - - TestRegistrationServices?.Invoke(services); - }); - } - - private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) - { - var httpContextAccessorMock = Substitute.For(); - using var scope = serviceProvider.CreateScope(); - httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; - - httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); - httpContextAccessorMock.HttpContext.Request.Scheme = "http"; - - return httpContextAccessorMock; - } -} diff --git a/src/Services/Identity/tests/IntegrationTest/Integration.Test.csproj b/src/Services/Identity/tests/IntegrationTest/Integration.Test.csproj index 2f07dab..d51304a 100644 --- a/src/Services/Identity/tests/IntegrationTest/Integration.Test.csproj +++ b/src/Services/Identity/tests/IntegrationTest/Integration.Test.csproj @@ -7,10 +7,10 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -22,7 +22,7 @@ - + diff --git a/src/Services/Identity/tests/IntegrationTest/IntegrationTestFixture.cs b/src/Services/Identity/tests/IntegrationTest/IntegrationTestFixture.cs index 7bb3fd9..271ad1d 100644 --- a/src/Services/Identity/tests/IntegrationTest/IntegrationTestFixture.cs +++ b/src/Services/Identity/tests/IntegrationTest/IntegrationTestFixture.cs @@ -2,16 +2,22 @@ using System.Net.Http; using System.Threading.Tasks; using BuildingBlocks.Domain.Model; -using BuildingBlocks.EFCore; +using BuildingBlocks.MassTransit; +using BuildingBlocks.Web; using Grpc.Net.Client; using Identity.Data; +using MassTransit; using MassTransit.Testing; using MediatR; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; using NSubstitute; +using Respawn; using Serilog; using Xunit; using Xunit.Abstractions; @@ -19,52 +25,81 @@ using Xunit.Abstractions; namespace Integration.Test; [CollectionDefinition(nameof(IntegrationTestFixture))] -public class FixtureCollection : ICollectionFixture { } +public class FixtureCollection : ICollectionFixture +{ +} public class IntegrationTestFixture : IAsyncLifetime { - private readonly CustomWebApplicationFactory _factory; - - public IntegrationTestFixture() - { - // Ref: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#basic-tests-with-the-default-webapplicationfactory - _factory = new CustomWebApplicationFactory(); - } - + private WebApplicationFactory _factory; + public Checkpoint Checkpoint { get; set; } + public Action? TestRegistrationServices { get; set; } public IServiceProvider ServiceProvider => _factory.Services; - public IConfiguration Configuration => _factory.Configuration; + public IConfiguration Configuration => _factory.Services.GetRequiredService(); public HttpClient HttpClient => _factory.CreateClient(); public ITestHarness TestHarness => CreateHarness(); public GrpcChannel Channel => CreateChannel(); - // ref: https://github.com/trbenning/serilog-sinks-xunit - public ILogger CreateLogger(ITestOutputHelper output) - { - if (output != null) - { - return new LoggerConfiguration() - .WriteTo.TestOutput(output) - .CreateLogger(); - } - - return null; - } - - public void RegisterTestServices(Action services) => _factory.TestRegistrationServices = services; - public virtual Task InitializeAsync() { + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.UseEnvironment("test"); + builder.ConfigureServices(services => + { + services.RemoveAll(typeof(IHostedService)); + services.ReplaceSingleton(AddHttpContextAccessorMock); + TestRegistrationServices?.Invoke(services); + services.AddMassTransitTestHarness(x => + { + x.UsingRabbitMq((context, cfg) => + { + var rabbitMqOptions = services.GetOptions("RabbitMq"); + var host = rabbitMqOptions.HostName; + + cfg.Host(host, h => + { + h.Username(rabbitMqOptions.UserName); + h.Password(rabbitMqOptions.Password); + }); + cfg.ConfigureEndpoints(context); + }); + }); + + Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + + TestRegistrationServices?.Invoke(services); + }); + }); + return Task.CompletedTask; } public virtual async Task DisposeAsync() { if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) - await _factory.Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); + await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _factory.DisposeAsync(); } + // ref: https://github.com/trbenning/serilog-sinks-xunit + public ILogger CreateLogger(ITestOutputHelper output) + { + if (output != null) + return new LoggerConfiguration() + .WriteTo.TestOutput(output) + .CreateLogger(); + + return null; + } + + public void RegisterTestServices(Action services) + { + TestRegistrationServices = services; + } + public async Task ExecuteScopeAsync(Func action) { using var scope = ServiceProvider.CreateScope(); @@ -213,4 +248,16 @@ public class IntegrationTestFixture : IAsyncLifetime { return GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient}); } + + private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) + { + var httpContextAccessorMock = Substitute.For(); + using var scope = serviceProvider.CreateScope(); + httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; + + httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); + httpContextAccessorMock.HttpContext.Request.Scheme = "http"; + + return httpContextAccessorMock; + } } diff --git a/src/Services/Passenger/tests/IntegrationTest/CustomWebApplicationFactory.cs b/src/Services/Passenger/tests/IntegrationTest/CustomWebApplicationFactory.cs deleted file mode 100644 index 90ee138..0000000 --- a/src/Services/Passenger/tests/IntegrationTest/CustomWebApplicationFactory.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using BuildingBlocks.Contracts.Grpc; -using BuildingBlocks.MassTransit; -using BuildingBlocks.Web; -using MassTransit; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Testing; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using NSubstitute; -using Respawn; - -public class CustomWebApplicationFactory : WebApplicationFactory -{ - public Checkpoint Checkpoint { get; set; } - public IConfiguration Configuration => Services.GetRequiredService(); - public Action? TestRegistrationServices { get; set; } - - protected override void ConfigureWebHost(IWebHostBuilder builder) - { - //https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests#set-the-environment - //https://stackoverflow.com/questions/43927955/should-getenvironmentvariable-work-in-xunit-test/43951218 - - //we could read env from our test launch setting or we can set it directly here - builder.UseEnvironment("test"); - - //The test app's builder.ConfigureTestServices callback is executed after the app's Startup.ConfigureServices code is executed. - builder.ConfigureTestServices(services => - { - services.RemoveAll(typeof(IHostedService)); - services.ReplaceSingleton(AddHttpContextAccessorMock); - TestRegistrationServices?.Invoke(services); - services.AddMassTransitTestHarness(x => - { - x.UsingRabbitMq((context, cfg) => - { - var rabbitMqOptions = services.GetOptions("RabbitMq"); - var host = rabbitMqOptions.HostName; - - cfg.Host(host, h => - { - h.Username(rabbitMqOptions.UserName); - h.Password(rabbitMqOptions.Password); - }); - cfg.ConfigureEndpoints(context); - }); - }); - - services.ReplaceServiceWithSingletonMock(); - - Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; - - TestRegistrationServices?.Invoke(services); - }); - } - - private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) - { - var httpContextAccessorMock = Substitute.For(); - using var scope = serviceProvider.CreateScope(); - httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; - - httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); - httpContextAccessorMock.HttpContext.Request.Scheme = "http"; - - return httpContextAccessorMock; - } -} diff --git a/src/Services/Passenger/tests/IntegrationTest/IntegrationTestFixture.cs b/src/Services/Passenger/tests/IntegrationTest/IntegrationTestFixture.cs index af2826d..709133e 100644 --- a/src/Services/Passenger/tests/IntegrationTest/IntegrationTestFixture.cs +++ b/src/Services/Passenger/tests/IntegrationTest/IntegrationTestFixture.cs @@ -1,25 +1,23 @@ using System; -using System.Linq; using System.Net.Http; -using System.Reflection; -using System.Security.Cryptography; using System.Threading.Tasks; using BuildingBlocks.Domain.Model; -using BuildingBlocks.EFCore; -using Grpc.Core; +using BuildingBlocks.MassTransit; +using BuildingBlocks.Web; using Grpc.Net.Client; -using MagicOnion; -using MagicOnion.Client; -using MagicOnion.Server; +using MassTransit; using MassTransit.Testing; using MediatR; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Moq; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Hosting; using NSubstitute; using Passenger.Data; +using Respawn; using Serilog; using Xunit; using Xunit.Abstractions; @@ -27,52 +25,81 @@ using Xunit.Abstractions; namespace Integration.Test; [CollectionDefinition(nameof(IntegrationTestFixture))] -public class FixtureCollection : ICollectionFixture { } +public class FixtureCollection : ICollectionFixture +{ +} public class IntegrationTestFixture : IAsyncLifetime { - private readonly CustomWebApplicationFactory _factory; - - public IntegrationTestFixture() - { - // Ref: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#basic-tests-with-the-default-webapplicationfactory - _factory = new CustomWebApplicationFactory(); - } - + private WebApplicationFactory _factory; + public Checkpoint Checkpoint { get; set; } + public Action? TestRegistrationServices { get; set; } public IServiceProvider ServiceProvider => _factory.Services; - public IConfiguration Configuration => _factory.Configuration; + public IConfiguration Configuration => _factory.Services.GetRequiredService(); public HttpClient HttpClient => _factory.CreateClient(); public ITestHarness TestHarness => CreateHarness(); public GrpcChannel Channel => CreateChannel(); - // ref: https://github.com/trbenning/serilog-sinks-xunit - public ILogger CreateLogger(ITestOutputHelper output) - { - if (output != null) - { - return new LoggerConfiguration() - .WriteTo.TestOutput(output) - .CreateLogger(); - } - - return null; - } - - public void RegisterTestServices(Action services) => _factory.TestRegistrationServices = services; - public virtual Task InitializeAsync() { + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.UseEnvironment("test"); + builder.ConfigureServices(services => + { + services.RemoveAll(typeof(IHostedService)); + services.ReplaceSingleton(AddHttpContextAccessorMock); + TestRegistrationServices?.Invoke(services); + services.AddMassTransitTestHarness(x => + { + x.UsingRabbitMq((context, cfg) => + { + var rabbitMqOptions = services.GetOptions("RabbitMq"); + var host = rabbitMqOptions.HostName; + + cfg.Host(host, h => + { + h.Username(rabbitMqOptions.UserName); + h.Password(rabbitMqOptions.Password); + }); + cfg.ConfigureEndpoints(context); + }); + }); + + Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + + TestRegistrationServices?.Invoke(services); + }); + }); + return Task.CompletedTask; } public virtual async Task DisposeAsync() { if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) - await _factory.Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); + await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _factory.DisposeAsync(); } + // ref: https://github.com/trbenning/serilog-sinks-xunit + public ILogger CreateLogger(ITestOutputHelper output) + { + if (output != null) + return new LoggerConfiguration() + .WriteTo.TestOutput(output) + .CreateLogger(); + + return null; + } + + public void RegisterTestServices(Action services) + { + TestRegistrationServices = services; + } + public async Task ExecuteScopeAsync(Func action) { using var scope = ServiceProvider.CreateScope(); @@ -221,4 +248,16 @@ public class IntegrationTestFixture : IAsyncLifetime { return GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient}); } + + private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) + { + var httpContextAccessorMock = Substitute.For(); + using var scope = serviceProvider.CreateScope(); + httpContextAccessorMock.HttpContext = new DefaultHttpContext {RequestServices = scope.ServiceProvider}; + + httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); + httpContextAccessorMock.HttpContext.Request.Scheme = "http"; + + return httpContextAccessorMock; + } }