using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; namespace GerbilManager.Tests; /// /// FEAT-13: In-Memory-Test-Host für Endpoint-Round-Trips. Ersetzt die /// Aspire/Npgsql-Registrierung durch SQLite in-memory (eine offene Verbindung /// hält die DB am Leben), Umgebung "Testing" überspringt Database.Migrate() /// (Npgsql-Migrationen laufen nicht auf SQLite) — Schema via EnsureCreated, /// inklusive der HasData-Seeds (73 Farbschläge + Zuchtprofil-Singleton). /// Vertrags-Dateien landen in einem Temp-Ordner, der mit dem Host stirbt. /// public sealed class ApiFactory : WebApplicationFactory { private readonly SqliteConnection _connection = new("DataSource=:memory:"); public string ContractRoot { get; } = Path.Combine(Path.GetTempPath(), $"gerbil-contract-tests-{Guid.NewGuid():N}"); protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment("Testing"); // Dummy, damit Aspires AddNpgsqlDbContext beim Host-Aufbau zufrieden ist; // die eigentliche Registrierung wird unten durch SQLite ersetzt. builder.UseSetting("ConnectionStrings:gerbilmanager", "Host=localhost;Database=test;Username=test;Password=test"); builder.UseSetting("Contracts:RootPath", ContractRoot); builder.ConfigureServices(services => { // EF 9+: AddDbContext registriert die Provider-Konfiguration als // IDbContextOptionsConfiguration — ohne deren Entfernung blieben // Npgsql UND SQLite registriert (ein Provider pro ServiceProvider). services.RemoveAll>(); services.RemoveAll>(); services.RemoveAll(); _connection.Open(); services.AddDbContext(o => o.UseSqlite(_connection)); using var provider = services.BuildServiceProvider(); using var scope = provider.CreateScope(); scope.ServiceProvider.GetRequiredService().Database.EnsureCreated(); }); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _connection.Dispose(); if (Directory.Exists(ContractRoot)) Directory.Delete(ContractRoot, recursive: true); } } }