using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Logging; using WalletService.Infrastructure; namespace WalletService.FunctionalTests; /// /// EN: Custom WebApplicationFactory for functional tests. /// VI: WebApplicationFactory tùy chỉnh cho functional tests. /// public class CustomWebApplicationFactory : WebApplicationFactory { private readonly string _databaseName = "TestDatabase_" + Guid.NewGuid().ToString(); protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment("Testing"); // EN: Configure services BEFORE the app configures itself // VI: Cấu hình services TRƯỚC KHI app tự cấu hình builder.ConfigureServices(services => { // EN: Remove ALL existing DbContext registrations // VI: Xóa TẤT CẢ các đăng ký DbContext hiện có RemoveExistingDbContextRegistrations(services); // EN: Remove PostgreSQL health check registrations // VI: Xóa các đăng ký health check PostgreSQL RemoveHealthCheckRegistrations(services); // EN: Add in-memory database for testing // VI: Thêm in-memory database để test services.AddDbContext(options => { options.UseInMemoryDatabase(_databaseName); options.EnableSensitiveDataLogging(); }); // EN: Add simple health checks for testing (no external dependencies) // VI: Thêm health checks đơn giản cho testing (không có external dependencies) services.AddHealthChecks(); // EN: Set logging level for debugging tests // VI: Đặt mức logging để debug tests services.AddLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); logging.AddFilter("Microsoft.EntityFrameworkCore", LogLevel.Warning); }); }); } private static void RemoveExistingDbContextRegistrations(IServiceCollection services) { // EN: Remove all DbContext-related registrations // VI: Xóa tất cả các đăng ký liên quan đến DbContext var descriptorsToRemove = services.Where(d => d.ServiceType == typeof(DbContextOptions) || d.ServiceType == typeof(WalletServiceContext) || d.ServiceType == typeof(DbContextOptions) || d.ServiceType.FullName?.Contains("EntityFrameworkCore") == true || d.ImplementationType?.FullName?.Contains("Npgsql") == true) .ToList(); foreach (var descriptor in descriptorsToRemove) { services.Remove(descriptor); } services.RemoveAll(typeof(DbContextOptions)); services.RemoveAll(typeof(DbContextOptions)); } private static void RemoveHealthCheckRegistrations(IServiceCollection services) { // EN: Remove health check registrations that depend on external services // VI: Xóa các health check registrations phụ thuộc vào external services var healthCheckDescriptors = services.Where(d => d.ServiceType == typeof(HealthCheckService) || d.ServiceType.FullName?.Contains("HealthCheck") == true || d.ImplementationType?.FullName?.Contains("NpgSql") == true || d.ImplementationType?.FullName?.Contains("Npgsql") == true) .ToList(); foreach (var descriptor in healthCheckDescriptors) { services.Remove(descriptor); } } /// /// EN: Ensure database is created after host is built /// VI: Đảm bảo database được tạo sau khi host được build /// protected override void ConfigureClient(HttpClient client) { base.ConfigureClient(client); // EN: Create the database when the first client is created // VI: Tạo database khi client đầu tiên được tạo using var scope = Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); db.Database.EnsureCreated(); } }