0
0
mirror of https://github.com/alex289/CleanArchitecture.git synced 2025-06-30 02:31:08 +00:00

feat: Add rabbit and redis to integration tests

This commit is contained in:
alex289 2024-04-25 19:59:53 +02:00
parent dca566cbf6
commit 4a8c102d00
No known key found for this signature in database
GPG Key ID: 573F77CD2D87F863
10 changed files with 174 additions and 18 deletions

View File

@ -72,7 +72,7 @@ builder.Services.AddLogging(x => x.AddSimpleConsole(console =>
console.IncludeScopes = true;
}));
if (builder.Environment.IsProduction())
if (builder.Environment.IsProduction() || !string.IsNullOrWhiteSpace(builder.Configuration["RedisHostName"]))
{
builder.Services.AddStackExchangeRedisCache(options =>
{
@ -95,12 +95,8 @@ using (var scope = app.Services.CreateScope())
var domainStoreDbContext = services.GetRequiredService<DomainNotificationStoreDbContext>();
appDbContext.EnsureMigrationsApplied();
if (app.Environment.EnvironmentName != "Integration")
{
storeDbContext.EnsureMigrationsApplied();
domainStoreDbContext.EnsureMigrationsApplied();
}
storeDbContext.EnsureMigrationsApplied();
domainStoreDbContext.EnsureMigrationsApplied();
}
if (app.Environment.IsDevelopment())

View File

@ -13,6 +13,7 @@
"Audience": "CleanArchitectureClient",
"Secret": "sD3v061gf8BxXgmxcHssasjdlkasjd87439284)@#(*"
},
"RedisHostName": "",
"RabbitMQ": {
"Host": "localhost",
"Username": "guest",

View File

@ -5,6 +5,7 @@
"Microsoft.AspNetCore": "Warning"
}
},
"RedisHostName": "",
"RabbitMQ": {
"Host": "localhost",
"Username": "guest",

View File

@ -5,7 +5,7 @@ using Xunit;
namespace CleanArchitecture.IntegrationTests.Fixtures;
public sealed class DatabaseFixture : IAsyncLifetime
public sealed class AccessorFixture : IAsyncLifetime
{
public static string TestRunDbName { get; } = $"CleanArchitecture-Integration-{Guid.NewGuid()}";
@ -13,11 +13,23 @@ public sealed class DatabaseFixture : IAsyncLifetime
{
var db = DatabaseAccessor.GetOrCreateAsync(TestRunDbName);
await db.DisposeAsync();
var redis = RedisAccessor.GetOrCreateAsync();
await redis.DisposeAsync();
var rabbit = RabbitmqAccessor.GetOrCreateAsync();
await rabbit.DisposeAsync();
}
public async Task InitializeAsync()
{
var db = DatabaseAccessor.GetOrCreateAsync(TestRunDbName);
await db.InitializeAsync();
var redis = RedisAccessor.GetOrCreateAsync();
await redis.InitializeAsync();
var rabbit = RabbitmqAccessor.GetOrCreateAsync();
await rabbit.InitializeAsync();
}
}

View File

@ -22,7 +22,7 @@ public class TestFixtureBase : IAsyncLifetime
Factory = new CleanArchitectureWebApplicationFactory(
RegisterCustomServicesHandler,
useTestAuthentication,
DatabaseFixture.TestRunDbName);
AccessorFixture.TestRunDbName);
ServerClient = Factory.CreateClient();
ServerClient.Timeout = TimeSpan.FromMinutes(5);

View File

@ -40,18 +40,31 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
base.ConfigureWebHost(builder);
var configuration = new ConfigurationBuilder()
.Build();
builder.ConfigureAppConfiguration(configurationBuilder =>
{
configurationBuilder.AddEnvironmentVariables();
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
var dbAccessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
var redisAccessor = RedisAccessor.GetOrCreateAsync();
var rabbitAccessor = RabbitmqAccessor.GetOrCreateAsync();
// Overwrite default connection string to our test instance db
// Overwrite default connection strings
configurationBuilder.AddInMemoryCollection([
new KeyValuePair<string, string?>(
"ConnectionStrings:DefaultConnection",
accessor.GetConnectionString())
dbAccessor.GetConnectionString()),
new KeyValuePair<string, string?>(
"RedisHostName",
redisAccessor.GetConnectionString()),
new KeyValuePair<string, string?>(
"RabbitMQ:Host",
rabbitAccessor.GetConnectionString())
]);
configuration = configurationBuilder.Build();
});
builder.ConfigureServices(services =>
@ -70,8 +83,14 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
using var scope = sp.CreateScope();
var scopedServices = scope.ServiceProvider;
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
var applicationDbContext = accessor.CreateDatabase(scopedServices);
var dbAccessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
dbAccessor.CreateDatabase(scopedServices);
var redisAccessor = RedisAccessor.GetOrCreateAsync();
redisAccessor.RegisterRedis(services, configuration);
var rabbitAccessor = RabbitmqAccessor.GetOrCreateAsync();
rabbitAccessor.RegisterRabbitmq(services, configuration);
_registerCustomServicesHandler?.Invoke(services, sp, scopedServices);
});
@ -85,7 +104,13 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
public override async ValueTask DisposeAsync()
{
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
await accessor.DisposeAsync();
var dbAccessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
await dbAccessor.DisposeAsync();
var redisAccessor = RedisAccessor.GetOrCreateAsync();
await redisAccessor.DisposeAsync();
var rabbitAccessor = RabbitmqAccessor.GetOrCreateAsync();
await rabbitAccessor.DisposeAsync();
}
}

View File

@ -18,7 +18,7 @@ public sealed class DatabaseAccessor
private bool _databaseCreated = false;
private readonly object _databaseCreationLock = new();
private const string _dbPassword = "12345678##as";
private const string _dbPassword = "234#AD224fD#ss";
private static readonly MsSqlContainer s_dbContainer = new MsSqlBuilder()
.WithPassword(_dbPassword)
.WithPortBinding(1433)
@ -61,6 +61,7 @@ public sealed class DatabaseAccessor
public async ValueTask DisposeAsync()
{
// Reset the database to its original state
var dropScript = $@"
USE MASTER;

View File

@ -0,0 +1,64 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using CleanArchitecture.Domain.Rabbitmq;
using CleanArchitecture.Domain.Rabbitmq.Extensions;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Testcontainers.RabbitMq;
using RabbitMqConfiguration = CleanArchitecture.Domain.Rabbitmq.RabbitMqConfiguration;
namespace CleanArchitecture.IntegrationTests.Infrastructure;
public sealed class RabbitmqAccessor
{
private static readonly ConcurrentDictionary<string, RabbitmqAccessor> s_accessors = new();
private static readonly RabbitMqContainer s_rabbitContainer = new RabbitMqBuilder()
.WithPortBinding(5672)
.Build();
public async Task InitializeAsync()
{
await s_rabbitContainer.StartAsync();
}
public async ValueTask DisposeAsync()
{
await s_rabbitContainer.DisposeAsync();
}
public string GetConnectionString()
{
return s_rabbitContainer.GetConnectionString();
}
public void RegisterRabbitmq(IServiceCollection serviceCollection, IConfiguration configuration)
{
var rabbitService = serviceCollection.FirstOrDefault(x =>
x.ServiceType == typeof(RabbitMqHandler));
if (rabbitService != null)
{
serviceCollection.Remove(rabbitService);
}
var rabbitConfig = serviceCollection.FirstOrDefault(x =>
x.ServiceType == typeof(RabbitMqConfiguration));
if (rabbitConfig != null)
{
serviceCollection.Remove(rabbitConfig);
}
serviceCollection.AddRabbitMqHandler(
configuration,
"RabbitMQ");
}
public static RabbitmqAccessor GetOrCreateAsync()
{
return s_accessors.GetOrAdd("rabbimq", _ => new RabbitmqAccessor());
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Testcontainers.Redis;
namespace CleanArchitecture.IntegrationTests.Infrastructure;
public sealed class RedisAccessor
{
private static readonly ConcurrentDictionary<string, RedisAccessor> s_accessors = new();
private static readonly RedisContainer s_redisContainer = new RedisBuilder()
.WithPortBinding(6379)
.Build();
public async Task InitializeAsync()
{
await s_redisContainer.StartAsync();
}
public async ValueTask DisposeAsync()
{
await s_redisContainer.DisposeAsync();
}
public string GetConnectionString()
{
return s_redisContainer.GetConnectionString();
}
public void RegisterRedis(IServiceCollection serviceCollection, IConfiguration configuration)
{
var distributedCache = serviceCollection.FirstOrDefault(x =>
x.ServiceType == typeof(IDistributedCache));
if (distributedCache != null)
{
serviceCollection.Remove(distributedCache);
}
serviceCollection.AddStackExchangeRedisCache(options =>
{
options.Configuration = configuration["RedisHostName"];
options.InstanceName = "clean-architecture";
});
}
public static RedisAccessor GetOrCreateAsync()
{
return s_accessors.GetOrAdd("redis", _ => new RedisAccessor());
}
}

View File

@ -5,6 +5,6 @@ namespace CleanArchitecture.IntegrationTests;
[CollectionDefinition("IntegrationTests", DisableParallelization = true)]
public sealed class IntegrationTestsCollection :
ICollectionFixture<DatabaseFixture>
ICollectionFixture<AccessorFixture>
{
}