Merge branch 'develop'

This commit is contained in:
meysamhadeli 2022-11-19 23:03:37 +03:30
commit 8242ebfa1a
15 changed files with 92 additions and 96 deletions

View File

@ -0,0 +1,53 @@
using BuildingBlocks.MassTransit;
using BuildingBlocks.Web;
using MassTransit;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
namespace BuildingBlocks.TestBase;
public class CustomWebApplicationFactory<TEntryPoint> : WebApplicationFactory<TEntryPoint>
where TEntryPoint : class
{
public Action<IServiceCollection> TestRegistrationServices { set; get; }
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("test");
builder.ConfigureServices(services =>
{
TestRegistrationServices?.Invoke(services);
services.ReplaceSingleton(AddHttpContextAccessorMock);
services.AddMassTransitTestHarness(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
var rabbitMqOptions = services.GetOptions<RabbitMqOptions>("RabbitMq");
var host = rabbitMqOptions.HostName;
cfg.Host(host, h =>
{
h.Username(rabbitMqOptions.UserName);
h.Password(rabbitMqOptions.Password);
});
cfg.ConfigureEndpoints(context);
});
});
});
}
private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider)
{
var httpContextAccessorMock = Substitute.For<IHttpContextAccessor>();
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;
}
}

View File

@ -2,24 +2,17 @@
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.EFCore; using BuildingBlocks.EFCore;
using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo; using BuildingBlocks.Mongo;
using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.PersistMessageProcessor;
using BuildingBlocks.Web;
using DotNet.Testcontainers.Containers; using DotNet.Testcontainers.Containers;
using Grpc.Net.Client; using Grpc.Net.Client;
using MassTransit;
using MassTransit.Testing; using MassTransit.Testing;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Mongo2Go; using Mongo2Go;
using NSubstitute;
using Respawn; using Respawn;
using Serilog; using Serilog;
using Xunit; using Xunit;
@ -27,15 +20,17 @@ using Xunit.Abstractions;
namespace BuildingBlocks.TestBase; namespace BuildingBlocks.TestBase;
public class IntegrationTestFactory<TEntryPoint> : IAsyncDisposable public class IntegrationTestFixture<TEntryPoint> : IDisposable
where TEntryPoint : class where TEntryPoint : class
{ {
private readonly WebApplicationFactory<TEntryPoint> _factory; private readonly CustomWebApplicationFactory<TEntryPoint> _factory;
private int Timeout => 180; private int Timeout => 180;
public Action<IServiceCollection> TestRegistrationServices { set; get; }
public HttpClient HttpClient => _factory.CreateClient(); public HttpClient HttpClient => _factory.CreateClient();
public ITestHarness TestHarness => CreateHarness(); public ITestHarness TestHarness => ServiceProvider.GetTestHarness();
public GrpcChannel Channel => CreateChannel();
public GrpcChannel Channel =>
GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient});
public IServiceProvider ServiceProvider => _factory.Services; public IServiceProvider ServiceProvider => _factory.Services;
public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>(); public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>();
@ -44,43 +39,20 @@ public class IntegrationTestFactory<TEntryPoint> : IAsyncDisposable
public MsSqlTestcontainer SqlPersistTestContainer; public MsSqlTestcontainer SqlPersistTestContainer;
public MongoDbTestcontainer MongoTestContainer; public MongoDbTestcontainer MongoTestContainer;
public IntegrationTestFactory() public IntegrationTestFixture()
{ {
_factory = new WebApplicationFactory<TEntryPoint>() // Ref: https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-6.0#basic-tests-with-the-default-webapplicationfactory
.WithWebHostBuilder(builder => _factory = new CustomWebApplicationFactory<TEntryPoint>();
{
builder.UseEnvironment("test");
builder.ConfigureServices(services =>
{
TestRegistrationServices?.Invoke(services);
services.ReplaceSingleton(AddHttpContextAccessorMock);
services.AddMassTransitTestHarness(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
var rabbitMqOptions = services.GetOptions<RabbitMqOptions>("RabbitMq");
var host = rabbitMqOptions.HostName;
cfg.Host(host, h =>
{
h.Username(rabbitMqOptions.UserName);
h.Password(rabbitMqOptions.Password);
});
cfg.ConfigureEndpoints(context);
});
});
});
});
} }
public async ValueTask DisposeAsync() public void Dispose()
{ {
await _factory.DisposeAsync(); _factory.Dispose();
} }
public virtual void RegisterServices(Action<IServiceCollection> services) public virtual void RegisterServices(Action<IServiceCollection> services)
{ {
TestRegistrationServices = services; _factory.TestRegistrationServices = services;
} }
// ref: https://github.com/trbenning/serilog-sinks-xunit // ref: https://github.com/trbenning/serilog-sinks-xunit
@ -169,32 +141,9 @@ public class IntegrationTestFactory<TEntryPoint> : IAsyncDisposable
}); });
}); });
} }
private ITestHarness CreateHarness()
{
var harness = ServiceProvider.GetTestHarness();
return harness;
}
private GrpcChannel CreateChannel()
{
return GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions {HttpClient = HttpClient});
}
private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider)
{
var httpContextAccessorMock = Substitute.For<IHttpContextAccessor>();
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;
}
} }
public class IntegrationTestFactory<TEntryPoint, TWContext> : IntegrationTestFactory<TEntryPoint> public class IntegrationTestFixture<TEntryPoint, TWContext> : IntegrationTestFixture<TEntryPoint>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
{ {
@ -301,7 +250,7 @@ public class IntegrationTestFactory<TEntryPoint, TWContext> : IntegrationTestFac
} }
} }
public class IntegrationTestFactory<TEntryPoint, TWContext, TRContext> : IntegrationTestFactory<TEntryPoint, TWContext> public class IntegrationTestFixture<TEntryPoint, TWContext, TRContext> : IntegrationTestFixture<TEntryPoint, TWContext>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
where TRContext : MongoDbContext where TRContext : MongoDbContext
@ -344,13 +293,13 @@ public class IntegrationTestFixtureCore<TEntryPoint> : IAsyncLifetime
set => Fixture.ServiceProvider.GetRequiredService<IOptions<MongoOptions>>().Value.ConnectionString = value; set => Fixture.ServiceProvider.GetRequiredService<IOptions<MongoOptions>>().Value.ConnectionString = value;
} }
public IntegrationTestFixtureCore(IntegrationTestFactory<TEntryPoint> integrationTestFixture) public IntegrationTestFixtureCore(IntegrationTestFixture<TEntryPoint> integrationTestFixture)
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
integrationTestFixture.RegisterServices(services => RegisterTestsServices(services)); integrationTestFixture.RegisterServices(services => RegisterTestsServices(services));
} }
public IntegrationTestFactory<TEntryPoint> Fixture { get; } public IntegrationTestFixture<TEntryPoint> Fixture { get; }
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
@ -409,43 +358,43 @@ public class IntegrationTestFixtureCore<TEntryPoint> : IAsyncLifetime
} }
public abstract class IntegrationTestBase<TEntryPoint> : IntegrationTestFixtureCore<TEntryPoint>, public abstract class IntegrationTestBase<TEntryPoint> : IntegrationTestFixtureCore<TEntryPoint>,
IClassFixture<IntegrationTestFactory<TEntryPoint>> IClassFixture<IntegrationTestFixture<TEntryPoint>>
where TEntryPoint : class where TEntryPoint : class
{ {
protected IntegrationTestBase( protected IntegrationTestBase(
IntegrationTestFactory<TEntryPoint> integrationTestFixture) : base(integrationTestFixture) IntegrationTestFixture<TEntryPoint> integrationTestFixture) : base(integrationTestFixture)
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }
public new IntegrationTestFactory<TEntryPoint> Fixture { get; } public IntegrationTestFixture<TEntryPoint> Fixture { get; }
} }
public abstract class IntegrationTestBase<TEntryPoint, TWContext> : IntegrationTestFixtureCore<TEntryPoint>, public abstract class IntegrationTestBase<TEntryPoint, TWContext> : IntegrationTestFixtureCore<TEntryPoint>,
IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext>> IClassFixture<IntegrationTestFixture<TEntryPoint, TWContext>>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
{ {
protected IntegrationTestBase( protected IntegrationTestBase(
IntegrationTestFactory<TEntryPoint, TWContext> integrationTestFixture) : base(integrationTestFixture) IntegrationTestFixture<TEntryPoint, TWContext> integrationTestFixture) : base(integrationTestFixture)
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }
public new IntegrationTestFactory<TEntryPoint, TWContext> Fixture { get; } public IntegrationTestFixture<TEntryPoint, TWContext> Fixture { get; }
} }
public abstract class IntegrationTestBase<TEntryPoint, TWContext, TRContext> : IntegrationTestFixtureCore<TEntryPoint>, public abstract class IntegrationTestBase<TEntryPoint, TWContext, TRContext> : IntegrationTestFixtureCore<TEntryPoint>,
IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext, TRContext>> IClassFixture<IntegrationTestFixture<TEntryPoint, TWContext, TRContext>>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
where TRContext : MongoDbContext where TRContext : MongoDbContext
{ {
protected IntegrationTestBase( protected IntegrationTestBase(
IntegrationTestFactory<TEntryPoint, TWContext, TRContext> integrationTestFixture) : base(integrationTestFixture) IntegrationTestFixture<TEntryPoint, TWContext, TRContext> integrationTestFixture) : base(integrationTestFixture)
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }
public new IntegrationTestFactory<TEntryPoint, TWContext, TRContext> Fixture { get; } public IntegrationTestFixture<TEntryPoint, TWContext, TRContext> Fixture { get; }
} }

View File

@ -27,7 +27,7 @@ public class CreateBookingTests : IntegrationTestBase<Program, PersistMessageDbC
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public CreateBookingTests( public CreateBookingTests(
IntegrationTestFactory<Program, PersistMessageDbContext, BookingReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, PersistMessageDbContext, BookingReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;

View File

@ -5,7 +5,6 @@ using Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads;
using Flight.Api; using Flight.Api;
using Flight.Data; using Flight.Data;
using FluentAssertions; using FluentAssertions;
using Grpc.Net.Client;
using Integration.Test.Fakes; using Integration.Test.Fakes;
using MassTransit; using MassTransit;
using MassTransit.Testing; using MassTransit.Testing;
@ -17,7 +16,7 @@ public class CreateAircraftTests : IntegrationTestBase<Program, FlightDbContext,
{ {
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public CreateAircraftTests(IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture) public CreateAircraftTests(IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;
} }

View File

@ -17,7 +17,7 @@ public class CreateAirportTests : IntegrationTestBase<Program, FlightDbContext,
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public CreateAirportTests( public CreateAirportTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;

View File

@ -17,7 +17,7 @@ public class CreateFlightTests : IntegrationTestBase<Program, FlightDbContext, F
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public CreateFlightTests( public CreateFlightTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;

View File

@ -20,7 +20,7 @@ public class DeleteFlightTests : IntegrationTestBase<Program, FlightDbContext, F
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public DeleteFlightTests( public DeleteFlightTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;

View File

@ -4,7 +4,6 @@ using BuildingBlocks.TestBase;
using Flight.Api; using Flight.Api;
using Flight.Data; using Flight.Data;
using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; using Flight.Flights.Features.CreateFlight.Commands.V1.Reads;
using Flight.Flights.Features.GetAvailableFlights;
using Flight.Flights.Features.GetAvailableFlights.Queries.V1; using Flight.Flights.Features.GetAvailableFlights.Queries.V1;
using FluentAssertions; using FluentAssertions;
using Integration.Test.Fakes; using Integration.Test.Fakes;
@ -15,7 +14,7 @@ namespace Integration.Test.Flight.Features;
public class GetAvailableFlightsTests : IntegrationTestBase<Program, FlightDbContext, FlightReadDbContext> public class GetAvailableFlightsTests : IntegrationTestBase<Program, FlightDbContext, FlightReadDbContext>
{ {
public GetAvailableFlightsTests( public GetAvailableFlightsTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture)
: base(integrationTestFixture) : base(integrationTestFixture)
{ {
} }

View File

@ -4,9 +4,7 @@ using Flight;
using Flight.Api; using Flight.Api;
using Flight.Data; using Flight.Data;
using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; using Flight.Flights.Features.CreateFlight.Commands.V1.Reads;
using Flight.Flights.Features.GetFlightById;
using Flight.Flights.Features.GetFlightById.Queries.V1; using Flight.Flights.Features.GetFlightById.Queries.V1;
using Flight.GrpcServer.Services;
using FluentAssertions; using FluentAssertions;
using Grpc.Net.Client; using Grpc.Net.Client;
using Integration.Test.Fakes; using Integration.Test.Fakes;
@ -19,7 +17,7 @@ public class GetFlightByIdTests : IntegrationTestBase<Program, FlightDbContext,
private readonly GrpcChannel _channel; private readonly GrpcChannel _channel;
public GetFlightByIdTests( public GetFlightByIdTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_channel = Fixture.Channel; _channel = Fixture.Channel;

View File

@ -15,7 +15,7 @@ public class UpdateFlightTests : IntegrationTestBase<Program, FlightDbContext, F
{ {
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public UpdateFlightTests(IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture) public UpdateFlightTests(IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;
} }

View File

@ -16,7 +16,7 @@ public class GetAvailableSeatsTests : IntegrationTestBase<Program, FlightDbConte
{ {
private readonly GrpcChannel _channel; private readonly GrpcChannel _channel;
public GetAvailableSeatsTests(IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture) public GetAvailableSeatsTests(IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(integrationTestFixture)
{ {
_channel = Fixture.Channel; _channel = Fixture.Channel;
} }

View File

@ -17,7 +17,7 @@ public class ReserveSeatTests : IntegrationTestBase<Program, FlightDbContext, Fl
private readonly GrpcChannel _channel; private readonly GrpcChannel _channel;
public ReserveSeatTests( public ReserveSeatTests(
IntegrationTestFactory<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base( IntegrationTestFixture<Program, FlightDbContext, FlightReadDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_channel = Fixture.Channel; _channel = Fixture.Channel;

View File

@ -2,7 +2,6 @@
using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Contracts.EventBus.Messages;
using BuildingBlocks.TestBase; using BuildingBlocks.TestBase;
using FluentAssertions; using FluentAssertions;
using Grpc.Net.Client;
using Identity.Api; using Identity.Api;
using Identity.Data; using Identity.Data;
using Integration.Test.Fakes; using Integration.Test.Fakes;
@ -16,7 +15,7 @@ public class RegisterNewUserTests : IntegrationTestBase<Program, IdentityContext
{ {
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public RegisterNewUserTests(IntegrationTestFactory<Program, IdentityContext> integrationTestFixture) : base(integrationTestFixture) public RegisterNewUserTests(IntegrationTestFixture<Program, IdentityContext> integrationTestFixture) : base(integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;
} }

View File

@ -14,7 +14,7 @@ public class CompleteRegisterPassengerTests : IntegrationTestBase<Program, Passe
{ {
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
public CompleteRegisterPassengerTests(IntegrationTestFactory<Program, PassengerDbContext> integrationTestFixture) : public CompleteRegisterPassengerTests(IntegrationTestFixture<Program, PassengerDbContext> integrationTestFixture) :
base(integrationTestFixture) base(integrationTestFixture)
{ {
_testHarness = Fixture.TestHarness; _testHarness = Fixture.TestHarness;

View File

@ -9,7 +9,6 @@ using Microsoft.Extensions.DependencyInjection;
using Passenger; using Passenger;
using Passenger.Api; using Passenger.Api;
using Passenger.Data; using Passenger.Data;
using Passenger.Passengers.Features.GetPassengerById;
using Passenger.Passengers.Features.GetPassengerById.Queries.V1; using Passenger.Passengers.Features.GetPassengerById.Queries.V1;
using Xunit; using Xunit;
@ -20,7 +19,7 @@ public class GetPassengerByIdTests : IntegrationTestBase<Program, PassengerDbCon
private readonly ITestHarness _testHarness; private readonly ITestHarness _testHarness;
private readonly GrpcChannel _channel; private readonly GrpcChannel _channel;
public GetPassengerByIdTests(IntegrationTestFactory<Program, PassengerDbContext> integrationTestFixture) : base( public GetPassengerByIdTests(IntegrationTestFixture<Program, PassengerDbContext> integrationTestFixture) : base(
integrationTestFixture) integrationTestFixture)
{ {
_channel = Fixture.Channel; _channel = Fixture.Channel;