using DodoSSH.Infrastructure; using Microsoft.EntityFrameworkCore; using Testcontainers.PostgreSql; using Xunit; namespace DodoSSH.Infrastructure.Tests; /// /// One PostgreSQL container per test assembly, migrated once. /// /// /// A container per test would dominate the runtime. Tests that write must therefore use distinct /// identifiers rather than assuming an empty database. /// public sealed class PostgresFixture : IAsyncLifetime { // Image passed to the constructor: the parameterless overload is obsolete in // Testcontainers 4.13 and pinning the tag here keeps the test image in step with the one // deploy/docker-compose.dev.yml uses. private readonly PostgreSqlContainer container = new PostgreSqlBuilder("postgres:18-alpine") .WithDatabase("dodossh") .WithUsername("postgres") .WithPassword("test") .Build(); /// Connection string for the running container. public string ConnectionString => container.GetConnectionString(); /// public async ValueTask InitializeAsync() { await container.StartAsync(); await using var context = CreateContext(); await context.Database.MigrateAsync(); } /// public async ValueTask DisposeAsync() => await container.DisposeAsync(); /// Creates a context against the container. public DodoDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseNpgsql(ConnectionString, npgsql => npgsql.MigrationsHistoryTable("__EFMigrationsHistory", DodoDbContext.SchemaName)) .UseSnakeCaseNamingConvention() .Options; return new DodoDbContext(options); } } /// Shares one container across every test class in the assembly. [CollectionDefinition(Name)] public sealed class PostgresCollection : ICollectionFixture { /// Collection name. public const string Name = "postgres"; }