using DotNet.Testcontainers.Images; using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Testcontainers.PostgreSql; using Vegasco.WebApi.Common; using Vegasco.WebApi.Persistence; namespace WebApi.Tests.Integration; public sealed class WebAppFactory : WebApplicationFactory, IAsyncLifetime { private readonly PostgreSqlContainer _database = new PostgreSqlBuilder() .WithImage(DockerImage) .WithImagePullPolicy(PullPolicy.Always) .Build(); private const string DockerImage = "postgres:16.3-alpine"; public HttpClient HttpClient => CreateClient(); private PostgresRespawner? _postgresRespawner; public async Task InitializeAsync() { await _database.StartAsync(); // Force application startup (i.e. initialization and validation) _ = CreateClient(); _postgresRespawner = await PostgresRespawner.CreateAsync(_database.GetConnectionString()); } protected override void ConfigureWebHost(IWebHostBuilder builder) { IEnumerable> customConfig = [ new KeyValuePair("ConnectionStrings:Database", _database.GetConnectionString()), new KeyValuePair("JWT:ValidAudience", "https://localhost"), new KeyValuePair("JWT:MetadataUrl", "https://localhost"), new KeyValuePair("JWT:NameClaimType", null), ]; builder.UseConfiguration(new ConfigurationBuilder() .AddInMemoryCollection(customConfig) .Build()); builder.ConfigureServices(services => { }); builder.ConfigureTestServices(services => { services.RemoveAll(); services.AddSingleton(); }); } public async Task ResetDatabaseAsync() { await _postgresRespawner!.ResetDatabaseAsync(); } async Task IAsyncLifetime.DisposeAsync() { _postgresRespawner!.Dispose(); await _database.DisposeAsync(); } }