Merge pull request #368 from meysamhadeli/fix/fix-ci-failed

Fix/fix ci failed
This commit is contained in:
Meysam Hadeli 2026-02-19 21:08:53 +03:30 committed by GitHub
commit 9164c770b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -39,7 +39,7 @@ using Testcontainers.PostgreSql;
using Testcontainers.RabbitMq; using Testcontainers.RabbitMq;
public class TestFixture<TEntryPoint> : IAsyncLifetime public class TestFixture<TEntryPoint> : IAsyncLifetime
where TEntryPoint : class where TEntryPoint : class
{ {
private readonly WebApplicationFactory<TEntryPoint> _factory; private readonly WebApplicationFactory<TEntryPoint> _factory;
private int Timeout => 120; // Second private int Timeout => 120; // Second
@ -60,11 +60,11 @@ where TEntryPoint : class
get get
{ {
var claims = new Dictionary<string, object> var claims = new Dictionary<string, object>
{ {
{ ClaimTypes.Name, "test@sample.com" }, { ClaimTypes.Name, "test@sample.com" },
{ ClaimTypes.Role, "admin" }, { ClaimTypes.Role, "admin" },
{ "scope", "flight-api" } { "scope", "flight-api" },
}; };
var httpClient = _factory.CreateClient(); var httpClient = _factory.CreateClient();
httpClient.SetFakeBearerToken(claims); // Uses FakeJwtBearer httpClient.SetFakeBearerToken(claims); // Uses FakeJwtBearer
@ -73,9 +73,7 @@ where TEntryPoint : class
} }
public GrpcChannel Channel => public GrpcChannel Channel =>
GrpcChannel.ForAddress( GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions { HttpClient = HttpClient });
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>();
@ -83,64 +81,76 @@ where TEntryPoint : class
protected TestFixture() protected TestFixture()
{ {
_factory = new WebApplicationFactory<TEntryPoint>() _factory = new WebApplicationFactory<TEntryPoint>().WithWebHostBuilder(builder =>
.WithWebHostBuilder( {
builder => builder.ConfigureAppConfiguration(AddCustomAppSettings);
builder.UseEnvironment("test");
builder.ConfigureServices(services =>
{
TestRegistrationServices?.Invoke(services);
services.ReplaceSingleton(AddHttpContextAccessorMock);
services.AddSingleton<PersistMessageBackgroundService>();
services.RemoveHostedService<PersistMessageBackgroundService>();
// Register all ITestDataSeeder implementations dynamically
services.Scan(scan =>
scan.FromApplicationDependencies() // Scan the current app and its dependencies
.AddClasses(classes => classes.AssignableTo<ITestDataSeeder>()) // Find classes that implement ITestDataSeeder
.AsImplementedInterfaces()
.WithScopedLifetime()
);
// Add Fake JWT Authentication - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
// https://github.com/webmotions/fake-authentication-jwtbearer
// https://github.com/webmotions/fake-authentication-jwtbearer/issues/14
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = FakeJwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = FakeJwtBearerDefaults.AuthenticationScheme;
})
.AddFakeJwtBearer();
// Mock Authorization Policies
services.AddAuthorization(options =>
{ {
builder.ConfigureAppConfiguration(AddCustomAppSettings); options.AddPolicy(
nameof(ApiScope),
builder.UseEnvironment("test"); policy =>
builder.ConfigureServices(
services =>
{ {
TestRegistrationServices?.Invoke(services); policy.AddAuthenticationSchemes(FakeJwtBearerDefaults.AuthenticationScheme);
services.ReplaceSingleton(AddHttpContextAccessorMock); policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "flight-api"); // Test-specific scope
services.AddSingleton<PersistMessageBackgroundService>(); }
services.RemoveHostedService<PersistMessageBackgroundService>(); );
// Register all ITestDataSeeder implementations dynamically
services.Scan(scan => scan
.FromApplicationDependencies() // Scan the current app and its dependencies
.AddClasses(classes => classes.AssignableTo<ITestDataSeeder>()) // Find classes that implement ITestDataSeeder
.AsImplementedInterfaces()
.WithScopedLifetime());
// Add Fake JWT Authentication - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
// https://github.com/webmotions/fake-authentication-jwtbearer
// https://github.com/webmotions/fake-authentication-jwtbearer/issues/14
services.AddAuthentication(
options =>
{
options.DefaultAuthenticateScheme = FakeJwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = FakeJwtBearerDefaults.AuthenticationScheme;
})
.AddFakeJwtBearer();
// Mock Authorization Policies
services.AddAuthorization(options =>
{
options.AddPolicy(nameof(ApiScope), policy =>
{
policy.AddAuthenticationSchemes(FakeJwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "flight-api"); // Test-specific scope
});
});
});
}); });
});
});
} }
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
CancellationTokenSource = new CancellationTokenSource(); CancellationTokenSource = new CancellationTokenSource();
await StartTestContainerAsync(); await StartTestContainerAsync();
if (ServiceProvider.GetService<ITestHarness>() is { } harness)
{
await harness.Start();
await Task.Delay(1000);
}
} }
public async Task DisposeAsync() public async Task DisposeAsync()
{ {
if (ServiceProvider.GetService<ITestHarness>() is { } harness)
{
await harness.Stop();
}
await StopTestContainerAsync(); await StopTestContainerAsync();
await _factory.DisposeAsync(); await _factory.DisposeAsync();
await CancellationTokenSource.CancelAsync(); await CancellationTokenSource.CancelAsync();
@ -158,10 +168,10 @@ where TEntryPoint : class
return null; return null;
var loggerFactory = LoggerFactory.Create(builder => var loggerFactory = LoggerFactory.Create(builder =>
{ {
builder.AddXunit(output); builder.AddXunit(output);
builder.SetMinimumLevel(LogLevel.Debug); builder.SetMinimumLevel(LogLevel.Debug);
}); });
return loggerFactory.CreateLogger("TestLogger"); return loggerFactory.CreateLogger("TestLogger");
} }
@ -180,67 +190,53 @@ where TEntryPoint : class
return result; return result;
} }
public Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request) public Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request)
{ {
return ExecuteScopeAsync( return ExecuteScopeAsync(sp =>
sp => {
{ var mediator = sp.GetRequiredService<IMediator>();
var mediator = sp.GetRequiredService<IMediator>();
return mediator.Send(request); return mediator.Send(request);
}); });
} }
public Task SendAsync(IRequest request) public Task SendAsync(IRequest request)
{ {
return ExecuteScopeAsync( return ExecuteScopeAsync(sp =>
sp => {
{ var mediator = sp.GetRequiredService<IMediator>();
var mediator = sp.GetRequiredService<IMediator>(); return mediator.Send(request);
return mediator.Send(request); });
});
} }
public async Task Publish<TMessage>( public async Task Publish<TMessage>(TMessage message, CancellationToken cancellationToken = default)
TMessage message, where TMessage : class, IEvent
CancellationToken cancellationToken = default
)
where TMessage : class, IEvent
{ {
await TestHarness.Bus.Publish(message, cancellationToken); await TestHarness.Bus.Publish(message, cancellationToken);
} }
public async Task<bool> WaitForPublishing<TMessage>( public async Task<bool> WaitForPublishing<TMessage>(CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default where TMessage : class, IEvent
)
where TMessage : class, IEvent
{ {
var result = await WaitUntilConditionMet( var result = await WaitUntilConditionMet(async () =>
async () => {
{ var published = await TestHarness.Published.Any<TMessage>(cancellationToken);
var published =
await TestHarness.Published.Any<TMessage>(cancellationToken);
return published; return published;
}); });
return result; return result;
} }
public async Task<bool> WaitForConsuming<TMessage>( public async Task<bool> WaitForConsuming<TMessage>(CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default where TMessage : class, IEvent
)
where TMessage : class, IEvent
{ {
var result = await WaitUntilConditionMet( var result = await WaitUntilConditionMet(async () =>
async () => {
{ var consumed = await TestHarness.Consumed.Any<TMessage>(cancellationToken);
var consumed =
await TestHarness.Consumed.Any<TMessage>(cancellationToken);
return consumed; return consumed;
}); });
return result; return result;
} }
@ -248,44 +244,31 @@ where TEntryPoint : class
public async Task<bool> ShouldProcessedPersistInternalCommand<TInternalCommand>( public async Task<bool> ShouldProcessedPersistInternalCommand<TInternalCommand>(
CancellationToken cancellationToken = default CancellationToken cancellationToken = default
) )
where TInternalCommand : class, IInternalCommand where TInternalCommand : class, IInternalCommand
{ {
var result = await WaitUntilConditionMet( var result = await WaitUntilConditionMet(async () =>
async () => {
{ return await ExecuteScopeAsync(async sp =>
return await ExecuteScopeAsync( {
async sp => var persistMessageProcessor = sp.GetService<IPersistMessageProcessor>();
{
var persistMessageProcessor =
sp.GetService<IPersistMessageProcessor>();
Guard.Against.Null( Guard.Against.Null(persistMessageProcessor, nameof(persistMessageProcessor));
persistMessageProcessor,
nameof(persistMessageProcessor));
var filter = var filter = await persistMessageProcessor.GetByFilterAsync(x =>
await persistMessageProcessor.GetByFilterAsync( x.DeliveryType == MessageDeliveryType.Internal && typeof(TInternalCommand).ToString() == x.DataType
x => );
x.DeliveryType ==
MessageDeliveryType.Internal &&
typeof(TInternalCommand).ToString() ==
x.DataType);
var res = filter.Any( var res = filter.Any(x => x.MessageStatus == MessageStatus.Processed);
x => x.MessageStatus == MessageStatus.Processed);
return res; return res;
}); });
}); });
return result; return result;
} }
// Ref: https://tech.energyhelpline.com/in-memory-testing-with-masstransit/ // Ref: https://tech.energyhelpline.com/in-memory-testing-with-masstransit/
private async Task<bool> WaitUntilConditionMet( private async Task<bool> WaitUntilConditionMet(Func<Task<bool>> conditionToMet, int? timeoutSecond = null)
Func<Task<bool>> conditionToMet,
int? timeoutSecond = null
)
{ {
var time = timeoutSecond ?? Timeout; var time = timeoutSecond ?? Timeout;
@ -338,39 +321,25 @@ where TEntryPoint : class
configuration.AddInMemoryCollection( configuration.AddInMemoryCollection(
new KeyValuePair<string, string>[] new KeyValuePair<string, string>[]
{ {
new( new("PostgresOptions:ConnectionString", PostgresTestcontainer.GetConnectionString()),
"PostgresOptions:ConnectionString", new("PostgresOptions:ConnectionString:Flight", PostgresTestcontainer.GetConnectionString()),
PostgresTestcontainer.GetConnectionString()), new("PostgresOptions:ConnectionString:Identity", PostgresTestcontainer.GetConnectionString()),
new( new("PostgresOptions:ConnectionString:Passenger", PostgresTestcontainer.GetConnectionString()),
"PostgresOptions:ConnectionString:Flight", new("PersistMessageOptions:ConnectionString", PostgresPersistTestContainer.GetConnectionString()),
PostgresTestcontainer.GetConnectionString()),
new(
"PostgresOptions:ConnectionString:Identity",
PostgresTestcontainer.GetConnectionString()),
new(
"PostgresOptions:ConnectionString:Passenger",
PostgresTestcontainer.GetConnectionString()),
new(
"PersistMessageOptions:ConnectionString",
PostgresPersistTestContainer.GetConnectionString()),
new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname), new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname),
new( new("RabbitMqOptions:UserName", TestContainers.RabbitMqContainerConfiguration.UserName),
"RabbitMqOptions:UserName", new("RabbitMqOptions:Password", TestContainers.RabbitMqContainerConfiguration.Password),
TestContainers.RabbitMqContainerConfiguration.UserName),
new(
"RabbitMqOptions:Password",
TestContainers.RabbitMqContainerConfiguration.Password),
new( new(
"RabbitMqOptions:Port", "RabbitMqOptions:Port",
RabbitMqTestContainer.GetMappedPublicPort( RabbitMqTestContainer
TestContainers.RabbitMqContainerConfiguration.Port) .GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration.Port)
.ToString(NumberFormatInfo.InvariantInfo)), .ToString(NumberFormatInfo.InvariantInfo)
),
new("MongoOptions:ConnectionString", MongoDbTestContainer.GetConnectionString()), new("MongoOptions:ConnectionString", MongoDbTestContainer.GetConnectionString()),
new("MongoOptions:DatabaseName", TestContainers.MongoContainerConfiguration.Name), new("MongoOptions:DatabaseName", TestContainers.MongoContainerConfiguration.Name),
new( new("EventStoreOptions:ConnectionString", EventStoreDbTestContainer.GetConnectionString()),
"EventStoreOptions:ConnectionString", }
EventStoreDbTestContainer.GetConnectionString()) );
});
} }
private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider) private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider)
@ -378,8 +347,7 @@ where TEntryPoint : class
var httpContextAccessorMock = Substitute.For<IHttpContextAccessor>(); var httpContextAccessorMock = Substitute.For<IHttpContextAccessor>();
using var scope = serviceProvider.CreateScope(); using var scope = serviceProvider.CreateScope();
httpContextAccessorMock.HttpContext = new DefaultHttpContext httpContextAccessorMock.HttpContext = new DefaultHttpContext { RequestServices = scope.ServiceProvider };
{ RequestServices = scope.ServiceProvider };
httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012); httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012);
httpContextAccessorMock.HttpContext.Request.Scheme = "http"; httpContextAccessorMock.HttpContext.Request.Scheme = "http";
@ -389,8 +357,8 @@ where TEntryPoint : class
} }
public class TestWriteFixture<TEntryPoint, TWContext> : TestFixture<TEntryPoint> public class TestWriteFixture<TEntryPoint, TWContext> : TestFixture<TEntryPoint>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
{ {
public Task ExecuteDbContextAsync(Func<TWContext, Task> action) public Task ExecuteDbContextAsync(Func<TWContext, Task> action)
{ {
@ -404,8 +372,7 @@ where TWContext : DbContext
public Task ExecuteDbContextAsync(Func<TWContext, IMediator, Task> action) public Task ExecuteDbContextAsync(Func<TWContext, IMediator, Task> action)
{ {
return ExecuteScopeAsync( return ExecuteScopeAsync(sp => action(sp.GetService<TWContext>(), sp.GetService<IMediator>()));
sp => action(sp.GetService<TWContext>(), sp.GetService<IMediator>()));
} }
public Task<T> ExecuteDbContextAsync<T>(Func<TWContext, Task<T>> action) public Task<T> ExecuteDbContextAsync<T>(Func<TWContext, Task<T>> action)
@ -420,69 +387,60 @@ where TWContext : DbContext
public Task<T> ExecuteDbContextAsync<T>(Func<TWContext, IMediator, Task<T>> action) public Task<T> ExecuteDbContextAsync<T>(Func<TWContext, IMediator, Task<T>> action)
{ {
return ExecuteScopeAsync( return ExecuteScopeAsync(sp => action(sp.GetService<TWContext>(), sp.GetService<IMediator>()));
sp => action(sp.GetService<TWContext>(), sp.GetService<IMediator>()));
} }
public Task InsertAsync<T>(params T[] entities) public Task InsertAsync<T>(params T[] entities)
where T : class where T : class
{ {
return ExecuteDbContextAsync( return ExecuteDbContextAsync(db =>
db => {
foreach (var entity in entities)
{ {
foreach (var entity in entities) db.Set<T>().Add(entity);
{ }
db.Set<T>().Add(entity);
}
return db.SaveChangesAsync(); return db.SaveChangesAsync();
}); });
} }
public async Task InsertAsync<TEntity>(TEntity entity) public async Task InsertAsync<TEntity>(TEntity entity)
where TEntity : class where TEntity : class
{ {
await ExecuteDbContextAsync( await ExecuteDbContextAsync(db =>
db => {
{ db.Set<TEntity>().Add(entity);
db.Set<TEntity>().Add(entity);
return db.SaveChangesAsync(); return db.SaveChangesAsync();
}); });
} }
public Task InsertAsync<TEntity, TEntity2>(TEntity entity, TEntity2 entity2) public Task InsertAsync<TEntity, TEntity2>(TEntity entity, TEntity2 entity2)
where TEntity : class where TEntity : class
where TEntity2 : class where TEntity2 : class
{ {
return ExecuteDbContextAsync( return ExecuteDbContextAsync(db =>
db => {
{ db.Set<TEntity>().Add(entity);
db.Set<TEntity>().Add(entity); db.Set<TEntity2>().Add(entity2);
db.Set<TEntity2>().Add(entity2);
return db.SaveChangesAsync(); return db.SaveChangesAsync();
}); });
} }
public Task InsertAsync<TEntity, TEntity2, TEntity3>( public Task InsertAsync<TEntity, TEntity2, TEntity3>(TEntity entity, TEntity2 entity2, TEntity3 entity3)
TEntity entity, where TEntity : class
TEntity2 entity2, where TEntity2 : class
TEntity3 entity3 where TEntity3 : class
)
where TEntity : class
where TEntity2 : class
where TEntity3 : class
{ {
return ExecuteDbContextAsync( return ExecuteDbContextAsync(db =>
db => {
{ db.Set<TEntity>().Add(entity);
db.Set<TEntity>().Add(entity); db.Set<TEntity2>().Add(entity2);
db.Set<TEntity2>().Add(entity2); db.Set<TEntity3>().Add(entity3);
db.Set<TEntity3>().Add(entity3);
return db.SaveChangesAsync(); return db.SaveChangesAsync();
}); });
} }
public Task InsertAsync<TEntity, TEntity2, TEntity3, TEntity4>( public Task InsertAsync<TEntity, TEntity2, TEntity3, TEntity4>(
@ -491,39 +449,38 @@ where TWContext : DbContext
TEntity3 entity3, TEntity3 entity3,
TEntity4 entity4 TEntity4 entity4
) )
where TEntity : class where TEntity : class
where TEntity2 : class where TEntity2 : class
where TEntity3 : class where TEntity3 : class
where TEntity4 : class where TEntity4 : class
{ {
return ExecuteDbContextAsync( return ExecuteDbContextAsync(db =>
db => {
{ db.Set<TEntity>().Add(entity);
db.Set<TEntity>().Add(entity); db.Set<TEntity2>().Add(entity2);
db.Set<TEntity2>().Add(entity2); db.Set<TEntity3>().Add(entity3);
db.Set<TEntity3>().Add(entity3); db.Set<TEntity4>().Add(entity4);
db.Set<TEntity4>().Add(entity4);
return db.SaveChangesAsync(); return db.SaveChangesAsync();
}); });
} }
public Task<T> FindAsync<T, TKey>(TKey id) public Task<T> FindAsync<T, TKey>(TKey id)
where T : class, IEntity where T : class, IEntity
{ {
return ExecuteDbContextAsync(db => db.Set<T>().FindAsync(id).AsTask()); return ExecuteDbContextAsync(db => db.Set<T>().FindAsync(id).AsTask());
} }
public Task<T> FirstOrDefaultAsync<T>() public Task<T> FirstOrDefaultAsync<T>()
where T : class, IEntity where T : class, IEntity
{ {
return ExecuteDbContextAsync(db => db.Set<T>().FirstOrDefaultAsync()); return ExecuteDbContextAsync(db => db.Set<T>().FirstOrDefaultAsync());
} }
} }
public class TestReadFixture<TEntryPoint, TRContext> : TestFixture<TEntryPoint> public class TestReadFixture<TEntryPoint, TRContext> : TestFixture<TEntryPoint>
where TEntryPoint : class where TEntryPoint : class
where TRContext : MongoDbContext where TRContext : MongoDbContext
{ {
public Task ExecuteReadContextAsync(Func<TRContext, Task> action) public Task ExecuteReadContextAsync(Func<TRContext, Task> action)
{ {
@ -536,21 +493,19 @@ where TRContext : MongoDbContext
} }
public async Task InsertMongoDbContextAsync<T>(string collectionName, params T[] entities) public async Task InsertMongoDbContextAsync<T>(string collectionName, params T[] entities)
where T : class where T : class
{ {
await ExecuteReadContextAsync( await ExecuteReadContextAsync(async db =>
async db => {
{ await db.GetCollection<T>(collectionName).InsertManyAsync(entities.ToList());
await db.GetCollection<T>(collectionName).InsertManyAsync(entities.ToList()); });
});
} }
} }
public class TestFixture<TEntryPoint, TWContext, TRContext> public class TestFixture<TEntryPoint, TWContext, TRContext> : TestWriteFixture<TEntryPoint, TWContext>
: TestWriteFixture<TEntryPoint, TWContext> where TEntryPoint : class
where TEntryPoint : class where TWContext : DbContext
where TWContext : DbContext where TRContext : MongoDbContext
where TRContext : MongoDbContext
{ {
public Task ExecuteReadContextAsync(Func<TRContext, Task> action) public Task ExecuteReadContextAsync(Func<TRContext, Task> action)
{ {
@ -563,18 +518,17 @@ where TRContext : MongoDbContext
} }
public async Task InsertMongoDbContextAsync<T>(string collectionName, params T[] entities) public async Task InsertMongoDbContextAsync<T>(string collectionName, params T[] entities)
where T : class where T : class
{ {
await ExecuteReadContextAsync( await ExecuteReadContextAsync(async db =>
async db => {
{ await db.GetCollection<T>(collectionName).InsertManyAsync(entities.ToList());
await db.GetCollection<T>(collectionName).InsertManyAsync(entities.ToList()); });
});
} }
} }
public class TestFixtureCore<TEntryPoint> : IAsyncLifetime public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
where TEntryPoint : class where TEntryPoint : class
{ {
private Respawner _reSpawnerDefaultDb; private Respawner _reSpawnerDefaultDb;
private Respawner _reSpawnerPersistDb; private Respawner _reSpawnerPersistDb;
@ -596,7 +550,6 @@ where TEntryPoint : class
public TestFixture<TEntryPoint> Fixture { get; } public TestFixture<TEntryPoint> Fixture { get; }
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
await InitPostgresAsync(); await InitPostgresAsync();
@ -623,12 +576,12 @@ where TEntryPoint : class
var dbContext = scope.ServiceProvider.GetRequiredService<PersistMessageDbContext>(); var dbContext = scope.ServiceProvider.GetRequiredService<PersistMessageDbContext>();
await dbContext.Database.EnsureCreatedAsync(); await dbContext.Database.EnsureCreatedAsync();
await Fixture.PersistMessageBackgroundService.StartAsync( await Fixture.PersistMessageBackgroundService.StartAsync(Fixture.CancellationTokenSource.Token);
Fixture.CancellationTokenSource.Token);
_reSpawnerPersistDb = await Respawner.CreateAsync( _reSpawnerPersistDb = await Respawner.CreateAsync(
PersistDbConnection, PersistDbConnection,
new RespawnerOptions { DbAdapter = DbAdapter.Postgres }); new RespawnerOptions { DbAdapter = DbAdapter.Postgres }
);
} }
if (!string.IsNullOrEmpty(postgresOptions?.ConnectionString) && _dbContextType != null) if (!string.IsNullOrEmpty(postgresOptions?.ConnectionString) && _dbContextType != null)
@ -644,12 +597,9 @@ where TEntryPoint : class
} }
_reSpawnerDefaultDb = await Respawner.CreateAsync( _reSpawnerDefaultDb = await Respawner.CreateAsync(
DefaultDbConnection, DefaultDbConnection,
new RespawnerOptions new RespawnerOptions { DbAdapter = DbAdapter.Postgres, TablesToIgnore = ["__EFMigrationsHistory"] }
{ );
DbAdapter = DbAdapter.Postgres,
TablesToIgnore = ["__EFMigrationsHistory",]
});
await SeedDataAsync(); await SeedDataAsync();
} }
@ -661,8 +611,7 @@ where TEntryPoint : class
{ {
await _reSpawnerPersistDb.ResetAsync(PersistDbConnection); await _reSpawnerPersistDb.ResetAsync(PersistDbConnection);
await Fixture.PersistMessageBackgroundService.StopAsync( await Fixture.PersistMessageBackgroundService.StopAsync(Fixture.CancellationTokenSource.Token);
Fixture.CancellationTokenSource.Token);
} }
if (DefaultDbConnection is not null) if (DefaultDbConnection is not null)
@ -677,31 +626,33 @@ where TEntryPoint : class
var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.GetConnectionString()); var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.GetConnectionString());
var collections = await dbClient var collections = await dbClient
.GetDatabase(TestContainers.MongoContainerConfiguration.Name) .GetDatabase(TestContainers.MongoContainerConfiguration.Name)
.ListCollectionsAsync(cancellationToken: cancellationToken); .ListCollectionsAsync(cancellationToken: cancellationToken);
foreach (var collection in collections.ToList()) foreach (var collection in collections.ToList())
{ {
await dbClient.GetDatabase(TestContainers.MongoContainerConfiguration.Name) await dbClient
.GetDatabase(TestContainers.MongoContainerConfiguration.Name)
.DropCollectionAsync(collection["name"].AsString, cancellationToken); .DropCollectionAsync(collection["name"].AsString, cancellationToken);
} }
} }
private async Task ResetRabbitMqAsync(CancellationToken cancellationToken = default) private async Task ResetRabbitMqAsync(CancellationToken cancellationToken = default)
{ {
var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort( var port =
TestContainers.RabbitMqContainerConfiguration Fixture.RabbitMqTestContainer?.GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration.ApiPort)
.ApiPort) ?? ?? TestContainers.RabbitMqContainerConfiguration.ApiPort;
TestContainers.RabbitMqContainerConfiguration.ApiPort;
var managementClient = new ManagementClient(Fixture.RabbitMqTestContainer?.Hostname, var managementClient = new ManagementClient(
Fixture.RabbitMqTestContainer?.Hostname,
TestContainers.RabbitMqContainerConfiguration?.UserName, TestContainers.RabbitMqContainerConfiguration?.UserName,
TestContainers.RabbitMqContainerConfiguration?.Password, port); TestContainers.RabbitMqContainerConfiguration?.Password,
port
);
var bd = await managementClient.GetBindingsAsync(cancellationToken); var bd = await managementClient.GetBindingsAsync(cancellationToken);
var bindings = bd.Where( var bindings = bd.Where(x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination));
x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination));
foreach (var binding in bindings) foreach (var binding in bindings)
{ {
@ -716,9 +667,7 @@ where TEntryPoint : class
} }
} }
protected virtual void RegisterTestsServices(IServiceCollection services) protected virtual void RegisterTestsServices(IServiceCollection services) { }
{
}
private async Task SeedDataAsync() private async Task SeedDataAsync()
{ {
@ -730,14 +679,15 @@ where TEntryPoint : class
} }
public abstract class TestReadBase<TEntryPoint, TRContext> : TestFixtureCore<TEntryPoint> public abstract class TestReadBase<TEntryPoint, TRContext> : TestFixtureCore<TEntryPoint>
// ,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext>> // ,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext>>
where TEntryPoint : class where TEntryPoint : class
where TRContext : MongoDbContext where TRContext : MongoDbContext
{ {
protected TestReadBase( protected TestReadBase(
TestReadFixture<TEntryPoint, TRContext> integrationTestFixture, TestReadFixture<TEntryPoint, TRContext> integrationTestFixture,
ITestOutputHelper outputHelper = null ITestOutputHelper outputHelper = null
) : base(integrationTestFixture, outputHelper) )
: base(integrationTestFixture, outputHelper)
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }
@ -746,14 +696,15 @@ where TRContext : MongoDbContext
} }
public abstract class TestWriteBase<TEntryPoint, TWContext> : TestFixtureCore<TEntryPoint> public abstract class TestWriteBase<TEntryPoint, TWContext> : TestFixtureCore<TEntryPoint>
//,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext>> //,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext>>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
{ {
protected TestWriteBase( protected TestWriteBase(
TestWriteFixture<TEntryPoint, TWContext> integrationTestFixture, TestWriteFixture<TEntryPoint, TWContext> integrationTestFixture,
ITestOutputHelper outputHelper = null ITestOutputHelper outputHelper = null
) : base(integrationTestFixture, outputHelper, typeof(TWContext)) )
: base(integrationTestFixture, outputHelper, typeof(TWContext))
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }
@ -762,16 +713,16 @@ where TWContext : DbContext
} }
public abstract class TestBase<TEntryPoint, TWContext, TRContext> : TestFixtureCore<TEntryPoint> public abstract class TestBase<TEntryPoint, TWContext, TRContext> : TestFixtureCore<TEntryPoint>
//,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext, TRContext>> //,IClassFixture<IntegrationTestFactory<TEntryPoint, TWContext, TRContext>>
where TEntryPoint : class where TEntryPoint : class
where TWContext : DbContext where TWContext : DbContext
where TRContext : MongoDbContext where TRContext : MongoDbContext
{ {
protected TestBase( protected TestBase(
TestFixture<TEntryPoint, TWContext, TRContext> integrationTestFixture, TestFixture<TEntryPoint, TWContext, TRContext> integrationTestFixture,
ITestOutputHelper outputHelper = null ITestOutputHelper outputHelper = null
) : )
base(integrationTestFixture, outputHelper, typeof(TWContext)) : base(integrationTestFixture, outputHelper, typeof(TWContext))
{ {
Fixture = integrationTestFixture; Fixture = integrationTestFixture;
} }