using MeterVault.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; using Testcontainers.PostgreSql; namespace MeterVault.Integration.Tests; /// /// Spins up exactly one TimescaleDB container per test run (shared via the "Timescale" /// collection) and applies migrations once. Tests reuse it and isolate themselves with Respawn. /// The image tag is pinned: the compression DDL (add_compression_policy) was renamed toward /// add_columnstore_policy in newer Timescale, so a floating tag would risk breaking migrations. /// public sealed class TimescaleFixture : IAsyncLifetime { private readonly PostgreSqlContainer _db = new PostgreSqlBuilder("timescale/timescaledb:2.17.2-pg16") .WithDatabase("metervault") .WithUsername("metervault") .WithPassword("metervault") .Build(); public string ConnectionString => _db.GetConnectionString(); public MeterVaultDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseNpgsql(ConnectionString, npgsql => npgsql.MigrationsAssembly(typeof(MeterVaultDbContext).Assembly.FullName)) .UseSnakeCaseNamingConvention() .Options; return new MeterVaultDbContext(options); } public async Task InitializeAsync() { await _db.StartAsync(); await using var ctx = CreateContext(); await ctx.Database.MigrateAsync(); } public async Task DisposeAsync() => await _db.DisposeAsync(); } /// Binds the shared to all tests in the "Timescale" collection. [CollectionDefinition("Timescale")] public sealed class TimescaleCollection : ICollectionFixture;