using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using System.Net.Http; using Testcontainers.PostgreSql; using Testcontainers.MongoDb; using Xunit; using System.Threading.Tasks; using System.Collections.Generic; using Knot.Shared.Kernel; using NSubstitute; namespace Knot.IntegrationTests; public abstract class BaseIntegrationTest : IAsyncLifetime { protected readonly PostgreSqlContainer _postgresContainer = new PostgreSqlBuilder() .WithImage("postgres:15-alpine") .Build(); protected readonly MongoDbContainer _mongoContainer = new MongoDbBuilder() .WithImage("mongo:6.0") .Build(); protected HttpClient _client; protected WebApplicationFactory _factory; protected readonly Guid _userId = Guid.NewGuid(); protected readonly IUserContext _userContextMock = Substitute.For(); public virtual async Task InitializeAsync() { await _postgresContainer.StartAsync(); await _mongoContainer.StartAsync(); _userContextMock.UserId.Returns(_userId); _userContextMock.IsAuthenticated.Returns(true); _factory = new IntegrationTestWebApplicationFactory( _postgresContainer.GetConnectionString(), _mongoContainer.GetConnectionString(), _userContextMock); _client = _factory.CreateClient(); } public virtual async Task DisposeAsync() { await _postgresContainer.StopAsync(); await _mongoContainer.StopAsync(); _factory?.Dispose(); _client?.Dispose(); } private class IntegrationTestWebApplicationFactory : WebApplicationFactory { private readonly string _pgConnectionString; private readonly string _mongoConnectionString; private readonly IUserContext _userContext; public IntegrationTestWebApplicationFactory(string pg, string mongo, IUserContext userContext) { _pgConnectionString = pg; _mongoConnectionString = mongo; _userContext = userContext; } protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureAppConfiguration((context, config) => { config.AddInMemoryCollection(new Dictionary { ["ConnectionStrings:DefaultConnection"] = _pgConnectionString, ["ConnectionStrings:MongoConnection"] = _mongoConnectionString, ["DATABASE_URL"] = _pgConnectionString, ["MONGO_CONNECTION"] = _mongoConnectionString, ["KNOT_MASTER_ENCRYPTION_KEY"] = "TestEncryptionKey_32CharactersLong!" }); }); builder.ConfigureTestServices(services => { services.AddScoped(_ => _userContext); }); } } }