This commit is contained in:
meysamhadeli 2022-07-02 00:44:10 +04:30
parent efcf745edc
commit 1be144f005
5 changed files with 258 additions and 174 deletions

View File

@ -1,12 +1,17 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Booking.Data; using Booking.Data;
using BuildingBlocks.Contracts.Grpc;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.MassTransit; using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo; using BuildingBlocks.Mongo;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Grpc.Net.Client; using Grpc.Net.Client;
using Integration.Test.Fakes;
using MagicOnion;
using MassTransit; using MassTransit;
using MassTransit.Testing; using MassTransit.Testing;
using MediatR; using MediatR;
@ -35,12 +40,11 @@ public class FixtureCollection : ICollectionFixture<IntegrationTestFixture>
public class IntegrationTestFixture : IAsyncLifetime public class IntegrationTestFixture : IAsyncLifetime
{ {
private WebApplicationFactory<Program> _factory; private WebApplicationFactory<Program> _factory;
public Checkpoint Checkpoint { get; set; } private Checkpoint _checkpoint;
private MongoDbRunner _mongoRunner; private MongoDbRunner _mongoRunner;
public Action<IServiceCollection>? TestRegistrationServices { get; set; } private IServiceProvider _serviceProvider;
public IServiceProvider ServiceProvider => _factory.Services; private Action<IServiceCollection>? _testRegistrationServices;
public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>(); private IConfiguration _configuration;
public HttpClient HttpClient => _factory.CreateClient(); public HttpClient HttpClient => _factory.CreateClient();
public ITestHarness TestHarness => CreateHarness(); public ITestHarness TestHarness => CreateHarness();
public GrpcChannel Channel => CreateChannel(); public GrpcChannel Channel => CreateChannel();
@ -53,68 +57,78 @@ public class IntegrationTestFixture : IAsyncLifetime
builder.UseEnvironment("test"); builder.UseEnvironment("test");
builder.ConfigureServices(services => builder.ConfigureServices(services =>
{ {
services.ReplaceSingleton(AddHttpContextAccessorMock); _testRegistrationServices?.Invoke(services);
TestRegistrationServices?.Invoke(services);
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);
});
});
Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
}); });
}); });
// _mongoRunner = MongoDbRunner.Start(); RegisterServices(services =>
// var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>(); {
// if (mongoOptions is not null) MockFlightGrpcServices(services);
// mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString; MockPassengerGrpcServices(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);
});
});
});
_serviceProvider = _factory.Services;
_configuration = _factory.Services.GetRequiredService<IConfiguration>();
_checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
_mongoRunner = MongoDbRunner.Start();
var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>();
if (mongoOptions.Value.ConnectionString != null)
mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString;
return Task.CompletedTask; return Task.CompletedTask;
} }
public void RegisterServices(Action<IServiceCollection> services) => _testRegistrationServices = services;
public virtual async Task DisposeAsync() public virtual async Task DisposeAsync()
{ {
if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) if (!string.IsNullOrEmpty(_configuration?.GetConnectionString("DefaultConnection")))
await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _checkpoint.Reset(_configuration?.GetConnectionString("DefaultConnection"));
await _factory.DisposeAsync(); await _factory.DisposeAsync();
_mongoRunner.Dispose();
} }
// ref: https://github.com/trbenning/serilog-sinks-xunit // ref: https://github.com/trbenning/serilog-sinks-xunit
public ILogger CreateLogger(ITestOutputHelper output) public ILogger CreateLogger(ITestOutputHelper output)
{ {
if (output != null) if (output != null)
{
return new LoggerConfiguration() return new LoggerConfiguration()
.WriteTo.TestOutput(output) .WriteTo.TestOutput(output)
.CreateLogger(); .CreateLogger();
}
return null; return null;
} }
public void RegisterTestServices(Action<IServiceCollection> services)
{
TestRegistrationServices = services;
}
public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action) public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
await action(scope.ServiceProvider); await action(scope.ServiceProvider);
} }
public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action) public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var result = await action(scope.ServiceProvider); var result = await action(scope.ServiceProvider);
@ -245,7 +259,7 @@ public class IntegrationTestFixture : IAsyncLifetime
private ITestHarness CreateHarness() private ITestHarness CreateHarness()
{ {
var harness = ServiceProvider.GetTestHarness(); var harness = _serviceProvider.GetTestHarness();
harness.Start().GetAwaiter().GetResult(); harness.Start().GetAwaiter().GetResult();
return harness; return harness;
} }
@ -266,4 +280,36 @@ public class IntegrationTestFixture : IAsyncLifetime
return httpContextAccessorMock; return httpContextAccessorMock;
} }
private void MockPassengerGrpcServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Singleton(x =>
{
var mock = Substitute.For<IPassengerGrpcService>();
mock.GetById(Arg.Any<long>())
.Returns(new UnaryResult<PassengerResponseDto>(new FakePassengerResponseDto().Generate()));
return mock;
}));
}
private void MockFlightGrpcServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Singleton(x =>
{
var mock = Substitute.For<IFlightGrpcService>();
mock.GetById(Arg.Any<long>())
.Returns(new UnaryResult<FlightResponseDto>(Task.FromResult(new FakeFlightResponseDto().Generate())));
mock.GetAvailableSeats(Arg.Any<long>())
.Returns(
new UnaryResult<IEnumerable<SeatResponseDto>>(Task.FromResult(FakeSeatsResponseDto.Generate())));
mock.ReserveSeat(new FakeReserveSeatRequestDto().Generate())
.Returns(new UnaryResult<SeatResponseDto>(Task.FromResult(FakeSeatsResponseDto.Generate().First())));
return mock;
}));
}
} }

View File

@ -2,14 +2,10 @@
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.EFCore;
using BuildingBlocks.MassTransit; using BuildingBlocks.MassTransit;
using BuildingBlocks.MessageProcessor;
using BuildingBlocks.Mongo; using BuildingBlocks.Mongo;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using DotNetCore.CAP.MongoDB;
using Flight.Data; using Flight.Data;
using FluentAssertions.Common;
using Grpc.Net.Client; using Grpc.Net.Client;
using MassTransit; using MassTransit;
using MassTransit.Testing; using MassTransit.Testing;
@ -17,11 +13,8 @@ using MediatR;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Mongo2Go; using Mongo2Go;
using NSubstitute; using NSubstitute;
@ -39,17 +32,76 @@ public class FixtureCollection : ICollectionFixture<IntegrationTestFixture>
public class IntegrationTestFixture : IAsyncLifetime public class IntegrationTestFixture : IAsyncLifetime
{ {
private Checkpoint _checkpoint;
private IConfiguration _configuration;
private WebApplicationFactory<Program> _factory; private WebApplicationFactory<Program> _factory;
private MongoDbRunner _mongoRunner; private MongoDbRunner _mongoRunner;
public Checkpoint Checkpoint { get; set; } private IServiceProvider _serviceProvider;
public Action<IServiceCollection>? TestRegistrationServices { get; set; } private Action<IServiceCollection>? _testRegistrationServices;
public IServiceProvider ServiceProvider => _factory.Services;
public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>();
public HttpClient HttpClient => _factory.CreateClient(); public HttpClient HttpClient => _factory.CreateClient();
public ITestHarness TestHarness => CreateHarness(); public ITestHarness TestHarness => CreateHarness();
public GrpcChannel Channel => CreateChannel(); public GrpcChannel Channel => CreateChannel();
public virtual Task InitializeAsync()
{
_factory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("test");
builder.ConfigureServices(services =>
{
_testRegistrationServices?.Invoke(services);
});
});
RegisterServices(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);
});
});
});
_serviceProvider = _factory.Services;
_configuration = _factory.Services.GetRequiredService<IConfiguration>();
_checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
_mongoRunner = MongoDbRunner.Start();
var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>();
if (mongoOptions.Value.ConnectionString != null)
mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString;
return Task.CompletedTask;
}
public virtual async Task DisposeAsync()
{
if (!string.IsNullOrEmpty(_configuration?.GetConnectionString("DefaultConnection")))
await _checkpoint.Reset(_configuration?.GetConnectionString("DefaultConnection"));
await _factory.DisposeAsync();
_mongoRunner.Dispose();
}
public void RegisterServices(Action<IServiceCollection> services)
{
_testRegistrationServices = services;
}
// ref: https://github.com/trbenning/serilog-sinks-xunit // ref: https://github.com/trbenning/serilog-sinks-xunit
public ILogger CreateLogger(ITestOutputHelper output) public ILogger CreateLogger(ITestOutputHelper output)
{ {
@ -63,61 +115,15 @@ public class IntegrationTestFixture : IAsyncLifetime
return null; return null;
} }
public void RegisterTestServices(Action<IServiceCollection> services) => TestRegistrationServices = services;
public virtual Task InitializeAsync()
{
_factory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("test");
builder.ConfigureServices(services =>
{
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);
});
});
Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
});
});
_mongoRunner = MongoDbRunner.Start();
var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>();
mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString;
return Task.CompletedTask;
}
public virtual async Task DisposeAsync()
{
if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection")))
await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection"));
await _factory.DisposeAsync();
_mongoRunner.Dispose();
}
public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action) public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
await action(scope.ServiceProvider); await action(scope.ServiceProvider);
} }
public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action) public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var result = await action(scope.ServiceProvider); var result = await action(scope.ServiceProvider);
@ -248,7 +254,7 @@ public class IntegrationTestFixture : IAsyncLifetime
private ITestHarness CreateHarness() private ITestHarness CreateHarness()
{ {
var harness = ServiceProvider.GetTestHarness(); var harness = _serviceProvider.GetTestHarness();
harness.Start().GetAwaiter().GetResult(); harness.Start().GetAwaiter().GetResult();
return harness; return harness;
} }

View File

@ -3,6 +3,7 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.MassTransit; using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Grpc.Net.Client; using Grpc.Net.Client;
using Identity.Data; using Identity.Data;
@ -14,8 +15,8 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options;
using Microsoft.Extensions.Hosting; using Mongo2Go;
using NSubstitute; using NSubstitute;
using Respawn; using Respawn;
using Serilog; using Serilog;
@ -31,15 +32,17 @@ public class FixtureCollection : ICollectionFixture<IntegrationTestFixture>
public class IntegrationTestFixture : IAsyncLifetime public class IntegrationTestFixture : IAsyncLifetime
{ {
private Checkpoint _checkpoint;
private IConfiguration _configuration;
private WebApplicationFactory<Program> _factory; private WebApplicationFactory<Program> _factory;
public Checkpoint Checkpoint { get; set; } private MongoDbRunner _mongoRunner;
public Action<IServiceCollection>? TestRegistrationServices { get; set; } private IServiceProvider _serviceProvider;
public IServiceProvider ServiceProvider => _factory.Services; private Action<IServiceCollection>? _testRegistrationServices;
public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>();
public HttpClient HttpClient => _factory.CreateClient(); public HttpClient HttpClient => _factory.CreateClient();
public ITestHarness TestHarness => CreateHarness(); public ITestHarness TestHarness => CreateHarness();
public GrpcChannel Channel => CreateChannel(); public GrpcChannel Channel => CreateChannel();
public virtual Task InitializeAsync() public virtual Task InitializeAsync()
{ {
_factory = new WebApplicationFactory<Program>() _factory = new WebApplicationFactory<Program>()
@ -48,66 +51,79 @@ public class IntegrationTestFixture : IAsyncLifetime
builder.UseEnvironment("test"); builder.UseEnvironment("test");
builder.ConfigureServices(services => builder.ConfigureServices(services =>
{ {
services.ReplaceSingleton(AddHttpContextAccessorMock); _testRegistrationServices?.Invoke(services);
TestRegistrationServices?.Invoke(services);
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);
});
});
Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
TestRegistrationServices?.Invoke(services);
}); });
}); });
RegisterServices(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);
});
});
});
_serviceProvider = _factory.Services;
_configuration = _factory.Services.GetRequiredService<IConfiguration>();
_checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
_mongoRunner = MongoDbRunner.Start();
var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>();
if (mongoOptions.Value.ConnectionString != null)
mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString;
return Task.CompletedTask; return Task.CompletedTask;
} }
public virtual async Task DisposeAsync() public virtual async Task DisposeAsync()
{ {
if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) if (!string.IsNullOrEmpty(_configuration?.GetConnectionString("DefaultConnection")))
await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _checkpoint.Reset(_configuration?.GetConnectionString("DefaultConnection"));
await _factory.DisposeAsync(); await _factory.DisposeAsync();
_mongoRunner.Dispose();
}
public void RegisterServices(Action<IServiceCollection> services)
{
_testRegistrationServices = services;
} }
// ref: https://github.com/trbenning/serilog-sinks-xunit // ref: https://github.com/trbenning/serilog-sinks-xunit
public ILogger CreateLogger(ITestOutputHelper output) public ILogger CreateLogger(ITestOutputHelper output)
{ {
if (output != null) if (output != null)
{
return new LoggerConfiguration() return new LoggerConfiguration()
.WriteTo.TestOutput(output) .WriteTo.TestOutput(output)
.CreateLogger(); .CreateLogger();
}
return null; return null;
} }
public void RegisterTestServices(Action<IServiceCollection> services)
{
TestRegistrationServices = services;
}
public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action) public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
await action(scope.ServiceProvider); await action(scope.ServiceProvider);
} }
public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action) public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var result = await action(scope.ServiceProvider); var result = await action(scope.ServiceProvider);
@ -238,7 +254,7 @@ public class IntegrationTestFixture : IAsyncLifetime
private ITestHarness CreateHarness() private ITestHarness CreateHarness()
{ {
var harness = ServiceProvider.GetTestHarness(); var harness = _serviceProvider.GetTestHarness();
harness.Start().GetAwaiter().GetResult(); harness.Start().GetAwaiter().GetResult();
return harness; return harness;
} }

View File

@ -9,7 +9,7 @@ public sealed class PassengerDbContext : AppDbContextBase
{ {
public const string DefaultSchema = "dbo"; public const string DefaultSchema = "dbo";
public PassengerDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options, httpContextAccessor) public PassengerDbContext(DbContextOptions<PassengerDbContext> options, IHttpContextAccessor httpContextAccessor) : base(options, httpContextAccessor)
{ {
} }

View File

@ -3,6 +3,7 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.MassTransit; using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Grpc.Net.Client; using Grpc.Net.Client;
using MassTransit; using MassTransit;
@ -13,8 +14,8 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options;
using Microsoft.Extensions.Hosting; using Mongo2Go;
using NSubstitute; using NSubstitute;
using Passenger.Data; using Passenger.Data;
using Respawn; using Respawn;
@ -31,15 +32,17 @@ public class FixtureCollection : ICollectionFixture<IntegrationTestFixture>
public class IntegrationTestFixture : IAsyncLifetime public class IntegrationTestFixture : IAsyncLifetime
{ {
private Checkpoint _checkpoint;
private IConfiguration _configuration;
private WebApplicationFactory<Program> _factory; private WebApplicationFactory<Program> _factory;
public Checkpoint Checkpoint { get; set; } private MongoDbRunner _mongoRunner;
public Action<IServiceCollection>? TestRegistrationServices { get; set; } private IServiceProvider _serviceProvider;
public IServiceProvider ServiceProvider => _factory.Services; private Action<IServiceCollection>? _testRegistrationServices;
public IConfiguration Configuration => _factory.Services.GetRequiredService<IConfiguration>();
public HttpClient HttpClient => _factory.CreateClient(); public HttpClient HttpClient => _factory.CreateClient();
public ITestHarness TestHarness => CreateHarness(); public ITestHarness TestHarness => CreateHarness();
public GrpcChannel Channel => CreateChannel(); public GrpcChannel Channel => CreateChannel();
public virtual Task InitializeAsync() public virtual Task InitializeAsync()
{ {
_factory = new WebApplicationFactory<Program>() _factory = new WebApplicationFactory<Program>()
@ -48,66 +51,79 @@ public class IntegrationTestFixture : IAsyncLifetime
builder.UseEnvironment("test"); builder.UseEnvironment("test");
builder.ConfigureServices(services => builder.ConfigureServices(services =>
{ {
services.ReplaceSingleton(AddHttpContextAccessorMock); _testRegistrationServices?.Invoke(services);
TestRegistrationServices?.Invoke(services);
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);
});
});
Checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
TestRegistrationServices?.Invoke(services);
}); });
}); });
RegisterServices(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);
});
});
});
_serviceProvider = _factory.Services;
_configuration = _factory.Services.GetRequiredService<IConfiguration>();
_checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}};
_mongoRunner = MongoDbRunner.Start();
var mongoOptions = _factory.Services.GetRequiredService<IOptions<MongoOptions>>();
if (mongoOptions.Value.ConnectionString != null)
mongoOptions.Value.ConnectionString = _mongoRunner.ConnectionString;
return Task.CompletedTask; return Task.CompletedTask;
} }
public virtual async Task DisposeAsync() public virtual async Task DisposeAsync()
{ {
if (!string.IsNullOrEmpty(Configuration?.GetConnectionString("DefaultConnection"))) if (!string.IsNullOrEmpty(_configuration?.GetConnectionString("DefaultConnection")))
await Checkpoint.Reset(Configuration?.GetConnectionString("DefaultConnection")); await _checkpoint.Reset(_configuration?.GetConnectionString("DefaultConnection"));
await _factory.DisposeAsync(); await _factory.DisposeAsync();
_mongoRunner.Dispose();
}
public void RegisterServices(Action<IServiceCollection> services)
{
_testRegistrationServices = services;
} }
// ref: https://github.com/trbenning/serilog-sinks-xunit // ref: https://github.com/trbenning/serilog-sinks-xunit
public ILogger CreateLogger(ITestOutputHelper output) public ILogger CreateLogger(ITestOutputHelper output)
{ {
if (output != null) if (output != null)
{
return new LoggerConfiguration() return new LoggerConfiguration()
.WriteTo.TestOutput(output) .WriteTo.TestOutput(output)
.CreateLogger(); .CreateLogger();
}
return null; return null;
} }
public void RegisterTestServices(Action<IServiceCollection> services)
{
TestRegistrationServices = services;
}
public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action) public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
await action(scope.ServiceProvider); await action(scope.ServiceProvider);
} }
public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action) public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
{ {
using var scope = ServiceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var result = await action(scope.ServiceProvider); var result = await action(scope.ServiceProvider);
@ -238,7 +254,7 @@ public class IntegrationTestFixture : IAsyncLifetime
private ITestHarness CreateHarness() private ITestHarness CreateHarness()
{ {
var harness = ServiceProvider.GetTestHarness(); var harness = _serviceProvider.GetTestHarness();
harness.Start().GetAwaiter().GetResult(); harness.Start().GetAwaiter().GetResult();
return harness; return harness;
} }