mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-11 02:20:20 +08:00
fix: Fix bug reset rabbitmq in test base
This commit is contained in:
parent
a58fad17d8
commit
8f3d2b9c8c
@ -13,7 +13,6 @@ root = true
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
@ -310,7 +309,7 @@ dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibili
|
||||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = none
|
||||
|
||||
##########################################
|
||||
# StyleCop Field Naming Rules
|
||||
@ -351,7 +350,6 @@ dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities =
|
||||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning
|
||||
|
||||
# Local variables must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
|
||||
|
||||
@ -18,9 +18,7 @@ public static class Extensions
|
||||
where TContext : DbContext, IDbContext
|
||||
{
|
||||
|
||||
services.AddOptions<DatabaseOptions>()
|
||||
.BindConfiguration(nameof(DatabaseOptions))
|
||||
.ValidateDataAnnotations();
|
||||
services.AddValidateOptions<DatabaseOptions>();
|
||||
|
||||
services.AddDbContext<TContext>((sp, options) =>
|
||||
{
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using System.Reflection;
|
||||
using BuildingBlocks.Core.Event;
|
||||
using BuildingBlocks.Utils;
|
||||
using BuildingBlocks.Web;
|
||||
using Humanizer;
|
||||
using MassTransit;
|
||||
@ -21,9 +20,7 @@ public static class Extensions
|
||||
public static IServiceCollection AddCustomMassTransit(this IServiceCollection services,
|
||||
IWebHostEnvironment env, Assembly assembly)
|
||||
{
|
||||
services.AddOptions<RabbitMqOptions>()
|
||||
.BindConfiguration(nameof(RabbitMqOptions))
|
||||
.ValidateDataAnnotations();
|
||||
services.AddValidateOptions<RabbitMqOptions>();
|
||||
|
||||
if (env.IsEnvironment("test"))
|
||||
{
|
||||
@ -34,10 +31,7 @@ public static class Extensions
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddMassTransit(configure =>
|
||||
{
|
||||
SetupMasstransitConfigurations(services, configure, assembly);
|
||||
});
|
||||
services.AddMassTransit(configure => { SetupMasstransitConfigurations(services, configure, assembly); });
|
||||
}
|
||||
|
||||
return services;
|
||||
|
||||
@ -3,6 +3,8 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BuildingBlocks.Mongo
|
||||
{
|
||||
using Web;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static IServiceCollection AddMongoDbContext<TContext>(
|
||||
@ -18,14 +20,14 @@ namespace BuildingBlocks.Mongo
|
||||
where TContextImplementation : MongoDbContext, TContextService
|
||||
{
|
||||
services.Configure<MongoOptions>(configuration.GetSection(nameof(MongoOptions)));
|
||||
|
||||
if (configurator is { })
|
||||
{
|
||||
services.Configure(nameof(MongoOptions), configurator);
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddOptions<MongoOptions>().Bind(configuration.GetSection(nameof(MongoOptions)))
|
||||
.ValidateDataAnnotations();
|
||||
services.AddValidateOptions<MongoOptions>();
|
||||
}
|
||||
|
||||
services.AddScoped(typeof(TContextService), typeof(TContextImplementation));
|
||||
|
||||
@ -9,9 +9,7 @@ public static class Extensions
|
||||
{
|
||||
public static IServiceCollection AddPersistMessageProcessor(this IServiceCollection services)
|
||||
{
|
||||
services.AddOptions<PersistMessageOptions>()
|
||||
.BindConfiguration(nameof(PersistMessageOptions))
|
||||
.ValidateDataAnnotations();
|
||||
services.AddValidateOptions<PersistMessageOptions>();
|
||||
|
||||
services.AddDbContext<PersistMessageDbContext>(options =>
|
||||
{
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
using BuildingBlocks.Core.Event;
|
||||
using BuildingBlocks.Core.Model;
|
||||
using BuildingBlocks.EFCore;
|
||||
using BuildingBlocks.MassTransit;
|
||||
using BuildingBlocks.Mongo;
|
||||
using BuildingBlocks.PersistMessageProcessor;
|
||||
using BuildingBlocks.Web;
|
||||
@ -19,7 +18,6 @@ using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using NSubstitute;
|
||||
using Respawn;
|
||||
@ -28,44 +26,49 @@ using Serilog;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using ILogger = Serilog.ILogger;
|
||||
|
||||
namespace BuildingBlocks.TestBase;
|
||||
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using WebMotions.Fake.Authentication.JwtBearer;
|
||||
|
||||
namespace BuildingBlocks.TestBase;
|
||||
|
||||
|
||||
|
||||
public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
where TEntryPoint : class
|
||||
{
|
||||
private readonly WebApplicationFactory<TEntryPoint> _factory;
|
||||
private int Timeout => 120; // Second
|
||||
|
||||
public MsSqlTestcontainer MsSqlTestContainer;
|
||||
public MsSqlTestcontainer MsSqlPersistTestContainer;
|
||||
private ITestHarness TestHarness => ServiceProvider?.GetTestHarness();
|
||||
private Action<IServiceCollection> TestRegistrationServices { get; set; }
|
||||
private MsSqlTestcontainer MsSqlTestContainer;
|
||||
private MsSqlTestcontainer MsSqlPersistTestContainer;
|
||||
public RabbitMqTestcontainer RabbitMqTestContainer;
|
||||
public MongoDbTestcontainer MongoDbTestContainer;
|
||||
|
||||
private ITestHarness TestHarness => ServiceProvider?.GetTestHarness();
|
||||
|
||||
public HttpClient HttpClient
|
||||
{
|
||||
get
|
||||
{
|
||||
var claims = new Dictionary<string, object> { { ClaimTypes.Name, "test@sample.com" }, { ClaimTypes.Role, "admin" }, };
|
||||
var claims =
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ ClaimTypes.Name, "test@sample.com" }, { ClaimTypes.Role, "admin" },
|
||||
};
|
||||
var httpClient = _factory?.CreateClient();
|
||||
httpClient.SetFakeBearerToken(claims);
|
||||
return httpClient;
|
||||
}
|
||||
}
|
||||
|
||||
public GrpcChannel Channel => GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions { HttpClient = HttpClient });
|
||||
public Action<IServiceCollection> TestRegistrationServices { get; set; }
|
||||
public GrpcChannel Channel =>
|
||||
GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions { HttpClient = HttpClient });
|
||||
|
||||
public IServiceProvider ServiceProvider => _factory?.Services;
|
||||
public IConfiguration Configuration => _factory?.Services.GetRequiredService<IConfiguration>();
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public TestFixture()
|
||||
protected TestFixture()
|
||||
{
|
||||
_factory = new WebApplicationFactory<TEntryPoint>()
|
||||
.WithWebHostBuilder(builder =>
|
||||
@ -98,7 +101,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await StopTestContainerAsync();
|
||||
_factory?.DisposeAsync();
|
||||
await _factory.DisposeAsync();
|
||||
}
|
||||
|
||||
public virtual void RegisterServices(Action<IServiceCollection> services)
|
||||
@ -119,13 +122,13 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
|
||||
protected async Task ExecuteScopeAsync(Func<IServiceProvider, Task> action)
|
||||
{
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
await action(scope.ServiceProvider);
|
||||
}
|
||||
|
||||
public async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
|
||||
protected async Task<T> ExecuteScopeAsync<T>(Func<IServiceProvider, Task<T>> action)
|
||||
{
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
|
||||
@ -157,7 +160,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
public async Task Publish<TMessage>(TMessage message, CancellationToken cancellationToken = default)
|
||||
where TMessage : class, IEvent
|
||||
{
|
||||
await TestHarness.Bus.Publish<TMessage>(message, cancellationToken);
|
||||
await TestHarness.Bus.Publish(message, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> WaitForPublishing<TMessage>(CancellationToken cancellationToken = default)
|
||||
@ -188,7 +191,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
}
|
||||
|
||||
// Ref: https://tech.energyhelpline.com/in-memory-testing-with-masstransit/
|
||||
public async Task<bool> WaitUntilConditionMet(Func<Task<bool>> conditionToMet, int? timeoutSecond = null)
|
||||
private async Task<bool> WaitUntilConditionMet(Func<Task<bool>> conditionToMet, int? timeoutSecond = null)
|
||||
{
|
||||
var time = timeoutSecond ?? Timeout;
|
||||
|
||||
@ -197,7 +200,10 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
var meet = await conditionToMet.Invoke();
|
||||
while (!meet)
|
||||
{
|
||||
if (timeoutExpired) return false;
|
||||
if (timeoutExpired)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
meet = await conditionToMet.Invoke();
|
||||
@ -257,9 +263,13 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
|
||||
configuration.AddInMemoryCollection(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new("DatabaseOptions:DefaultConnection", MsSqlTestContainer.ConnectionString + "TrustServerCertificate=True"),
|
||||
new("PersistMessageOptions:ConnectionString", MsSqlPersistTestContainer.ConnectionString + "TrustServerCertificate=True"), new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname),
|
||||
new("RabbitMqOptions:UserName", RabbitMqTestContainer.Username), new("RabbitMqOptions:Password", RabbitMqTestContainer.Password), new("RabbitMqOptions:Port", RabbitMqTestContainer.Port.ToString()),
|
||||
new("MongoOptions:ConnectionString", MongoDbTestContainer.ConnectionString), new("MongoOptions:DatabaseName", MongoDbTestContainer.Database)
|
||||
new("PersistMessageOptions:ConnectionString", MsSqlPersistTestContainer.ConnectionString + "TrustServerCertificate=True"),
|
||||
new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname),
|
||||
new("RabbitMqOptions:UserName", RabbitMqTestContainer.Username),
|
||||
new("RabbitMqOptions:Password", RabbitMqTestContainer.Password),
|
||||
new("RabbitMqOptions:Port", RabbitMqTestContainer.Port.ToString()),
|
||||
new("MongoOptions:ConnectionString", MongoDbTestContainer.ConnectionString),
|
||||
new("MongoOptions:DatabaseName", MongoDbTestContainer.Database)
|
||||
});
|
||||
}
|
||||
|
||||
@ -314,7 +324,10 @@ public class TestWriteFixture<TEntryPoint, TWContext> : TestFixture<TEntryPoint>
|
||||
{
|
||||
return ExecuteDbContextAsync(db =>
|
||||
{
|
||||
foreach (var entity in entities) db.Set<T>().Add(entity);
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
db.Set<T>().Add(entity);
|
||||
}
|
||||
|
||||
return db.SaveChangesAsync();
|
||||
});
|
||||
@ -446,10 +459,8 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
|
||||
|
||||
private async Task InitSqlAsync()
|
||||
{
|
||||
await ResetSqlAsync();
|
||||
|
||||
var databaseOptions = Fixture.ServiceProvider.GetRequiredService<IOptions<DatabaseOptions>>()?.Value;
|
||||
var persistOptions = Fixture.ServiceProvider.GetRequiredService<IOptions<PersistMessageOptions>>()?.Value;
|
||||
var databaseOptions = Fixture.ServiceProvider.GetRequiredService<DatabaseOptions>();
|
||||
var persistOptions = Fixture.ServiceProvider.GetRequiredService<PersistMessageOptions>();
|
||||
|
||||
if (!string.IsNullOrEmpty(persistOptions?.ConnectionString))
|
||||
{
|
||||
@ -475,15 +486,20 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
|
||||
private async Task ResetSqlAsync()
|
||||
{
|
||||
if (PersistDbConnection is not null)
|
||||
{
|
||||
await _reSpawnerPersistDb.ResetAsync(PersistDbConnection);
|
||||
}
|
||||
|
||||
if (DefaultDbConnection is not null)
|
||||
{
|
||||
await _reSpawnerDefaultDb.ResetAsync(DefaultDbConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ResetMongoAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
//https://stackoverflow.com/questions/3366397/delete-everything-in-a-mongodb-database
|
||||
MongoClient dbClient = new MongoClient(Fixture.MongoDbTestContainer?.ConnectionString);
|
||||
var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.ConnectionString);
|
||||
var collections = await dbClient.GetDatabase(Fixture.MongoDbTestContainer?.Database)
|
||||
.ListCollectionsAsync(cancellationToken: cancellationToken);
|
||||
|
||||
@ -498,10 +514,8 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
|
||||
{
|
||||
var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort(15672) ?? 15672;
|
||||
|
||||
var rabbitmqOptions = Fixture.ServiceProvider.GetRequiredService<IOptions<RabbitMqOptions>>()?.Value;
|
||||
|
||||
var managementClient = new ManagementClient(rabbitmqOptions?.HostName, rabbitmqOptions?.UserName,
|
||||
rabbitmqOptions?.Password, port);
|
||||
var managementClient = new ManagementClient(Fixture.RabbitMqTestContainer?.Hostname, Fixture.RabbitMqTestContainer?.Username,
|
||||
Fixture.RabbitMqTestContainer?.Password, port);
|
||||
|
||||
var bd = await managementClient.GetBindingsAsync(cancellationToken);
|
||||
var bindings = bd.Where(x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination));
|
||||
@ -528,7 +542,10 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
|
||||
using var scope = Fixture.ServiceProvider.CreateScope();
|
||||
|
||||
var seeders = scope.ServiceProvider.GetServices<IDataSeeder>();
|
||||
foreach (var seeder in seeders) await seeder.SeedAllAsync();
|
||||
foreach (var seeder in seeders)
|
||||
{
|
||||
await seeder.SeedAllAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BuildingBlocks.Web;
|
||||
|
||||
using MassTransit;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
public static class ConfigurationExtensions
|
||||
{
|
||||
public static TModel GetOptions<TModel>(this IConfiguration configuration, string section) where TModel : new()
|
||||
@ -27,4 +30,13 @@ public static class ConfigurationExtensions
|
||||
app.Configuration?.GetSection(section).Bind(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static void AddValidateOptions<TModel>(this IServiceCollection service) where TModel : class, new()
|
||||
{
|
||||
service.AddOptions<TModel>()
|
||||
.BindConfiguration(typeof(TModel).Name)
|
||||
.ValidateDataAnnotations();
|
||||
|
||||
service.AddSingleton(x => x.GetRequiredService<IOptions<TModel>>().Value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using AutoBogus;
|
||||
using Identity.Identity.Features.RegisterNewUser;
|
||||
using Identity.Identity.Features.RegisterNewUser.Commands.V1;
|
||||
|
||||
namespace Integration.Test.Fakes;
|
||||
@ -8,7 +7,7 @@ public class FakeRegisterNewUserCommand : AutoFaker<RegisterNewUserCommand>
|
||||
{
|
||||
public FakeRegisterNewUserCommand()
|
||||
{
|
||||
RuleFor(r => r.Username, _ => "TestUser");
|
||||
RuleFor(r => r.Username, x => x.Random.Uuid().ToString());
|
||||
RuleFor(r => r.Password, _ => "Password@123");
|
||||
RuleFor(r => r.ConfirmPassword, _ => "Password@123");
|
||||
RuleFor(r => r.Email, _ => "test@test.com");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user