using JSMR.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using MySqlConnector; using Testcontainers.MariaDb; namespace JSMR.Tests.Fixtures; public class MariaDbFixture : IAsyncLifetime { const int MajorVersion = 10; const int MinorVersion = 11; const int Build = 6; public MariaDbContainer? MariaDbContainer { get; private set; } public string ConnectionString { get; private set; } = default!; public async ValueTask InitializeAsync() { MariaDbContainer = new MariaDbBuilder() .WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}") .Build(); await MariaDbContainer.StartAsync(); ConnectionString = MariaDbContainer.GetConnectionString(); await using AppDbContext context = CreateDbContext(); await context.Database.EnsureCreatedAsync(); //await context.Database.MigrateAsync(); // Testing await OnInitializedAsync(context); } protected virtual Task OnInitializedAsync(AppDbContext context) { return Task.FromResult(Task.CompletedTask); } public async ValueTask DisposeAsync() { if (MariaDbContainer is not null) { await MariaDbContainer.StopAsync(); await MariaDbContainer.DisposeAsync(); } GC.SuppressFinalize(this); } public AppDbContext CreateDbContext() { MySqlServerVersion serverVersion = new(new Version(MajorVersion, MinorVersion, Build)); DbContextOptions options = new DbContextOptionsBuilder() .UseMySql(ConnectionString, serverVersion, o => o.EnableRetryOnFailure()) .EnableSensitiveDataLogging() .Options; return new AppDbContext(options); } public async Task ResetAsync() { await using AppDbContext context = CreateDbContext(); await context.Database.EnsureDeletedAsync(); await context.Database.EnsureCreatedAsync(); } } public static class MariaTestDb { public static async Task CreateIsolatedAsync(string rootConnectionString, Func? seed = null) { string databaseName = $"t_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}"; await CreateDatabaseAsync(rootConnectionString, databaseName); MySqlConnectionStringBuilder connectionStringBuilder = new(rootConnectionString) { Database = databaseName }; AppDbContext dbContext = CreateDbContext(connectionStringBuilder.ConnectionString); await dbContext.Database.EnsureCreatedAsync(); if (seed != null) await seed(dbContext); return dbContext; } private static async Task CreateDatabaseAsync(string rootConnectionString, string databaseName) { await using MySqlConnection connection = new(rootConnectionString); await connection.OpenAsync(); await using MySqlCommand command = connection.CreateCommand(); command.CommandText = $"CREATE DATABASE `{databaseName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"; await command.ExecuteNonQueryAsync(); } private static AppDbContext CreateDbContext(string connectionString) { DbContextOptions options = new DbContextOptionsBuilder() .UseMySql(connectionString, ServerVersion.AutoDetect(connectionString), o => o.EnableRetryOnFailure()) .EnableSensitiveDataLogging() .Options; return new AppDbContext(options); } }