Fix integration test infrastructure

- Create CustomWebApplicationFactory to properly handle DI
- Fix IntegrationTestBase to use proper service scope pattern
- Update AuthIntegrationTests and EventsIntegrationTests to use CustomWebApplicationFactory
- Resolve EF Core provider conflict by using ConfigureWebHost override

Tests now run: 7 passed, 6 failed (auth/response format issues)
This commit is contained in:
Denis Urs Rudolph
2026-04-09 21:11:03 +02:00
parent 13c9c8aa68
commit 0cdb391393
439 changed files with 6440 additions and 31 deletions
@@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
@@ -9,41 +10,51 @@ using Xunit;
namespace backend.Tests.Integration;
public class IntegrationTestBase : IClassFixture<WebApplicationFactory<Program>>
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected readonly WebApplicationFactory<Program> _factory;
protected readonly HttpClient _client;
protected readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
public IntegrationTestBase(WebApplicationFactory<Program> factory)
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
_factory = factory.WithWebHostBuilder(builder =>
builder.ConfigureServices(services =>
{
builder.ConfigureServices(services =>
// Remove all DbContextOptions registrations
var descriptors = services.Where(
d => d.ServiceType == typeof(DbContextOptions<RacePlannerDbContext>) ||
d.ServiceType.Name.Contains("DbContextOptions")).ToList();
foreach (var descriptor in descriptors)
{
// Replace the database context with an in-memory database
var descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<RacePlannerDbContext>));
if (descriptor != null)
{
services.Remove(descriptor);
}
services.Remove(descriptor);
}
services.AddDbContext<RacePlannerDbContext>(options =>
{
options.UseInMemoryDatabase("IntegrationTestDb");
});
// Ensure the database is created and seeded
var sp = services.BuildServiceProvider();
using var scope = sp.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<RacePlannerDbContext>();
db.Database.EnsureCreated();
// Add in-memory database
services.AddDbContext<RacePlannerDbContext>(options =>
{
options.UseInMemoryDatabase(Guid.NewGuid().ToString());
});
});
}
}
public abstract class IntegrationTestBase : IClassFixture<CustomWebApplicationFactory>, IDisposable
{
protected readonly CustomWebApplicationFactory _factory;
protected readonly HttpClient _client;
protected readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
protected readonly IServiceScope _scope;
protected readonly RacePlannerDbContext _dbContext;
protected IntegrationTestBase(CustomWebApplicationFactory factory)
{
_factory = factory;
_client = _factory.CreateClient();
_scope = _factory.Services.CreateScope();
_dbContext = _scope.ServiceProvider.GetRequiredService<RacePlannerDbContext>();
_dbContext.Database.EnsureCreated();
}
public void Dispose()
{
_scope.Dispose();
}
protected HttpClient CreateAuthenticatedClient(string token = "")