Files
raceplanner/tests/integration/backend/IntegrationTestBase.cs
T

101 lines
3.4 KiB
C#
Raw Normal View History

2026-04-09 21:11:03 +02:00
using Microsoft.AspNetCore.Hosting;
2026-04-08 20:23:48 +02:00
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RacePlannerApi.Data;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;
using Xunit;
namespace backend.Tests.Integration;
2026-04-09 21:11:03 +02:00
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
2026-04-08 20:23:48 +02:00
{
// Use a static database name so all tests in the same process share the database
private static readonly string _databaseName = $"IntegrationTestDb_{Guid.NewGuid():N}";
2026-04-09 21:11:03 +02:00
protected override void ConfigureWebHost(IWebHostBuilder builder)
2026-04-08 20:23:48 +02:00
{
2026-04-09 21:11:03 +02:00
builder.ConfigureServices(services =>
2026-04-08 20:23:48 +02:00
{
2026-04-09 21:11:03 +02:00
// 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)
2026-04-08 20:23:48 +02:00
{
2026-04-09 21:11:03 +02:00
services.Remove(descriptor);
}
2026-04-08 20:23:48 +02:00
// Add in-memory database with consistent name
2026-04-09 21:11:03 +02:00
services.AddDbContext<RacePlannerDbContext>(options =>
{
options.UseInMemoryDatabase(_databaseName);
2026-04-08 20:23:48 +02:00
});
});
2026-04-09 21:11:03 +02:00
}
}
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;
2026-04-08 20:23:48 +02:00
2026-04-09 21:11:03 +02:00
protected IntegrationTestBase(CustomWebApplicationFactory factory)
{
_factory = factory;
2026-04-08 20:23:48 +02:00
_client = _factory.CreateClient();
2026-04-09 21:11:03 +02:00
_scope = _factory.Services.CreateScope();
_dbContext = _scope.ServiceProvider.GetRequiredService<RacePlannerDbContext>();
_dbContext.Database.EnsureCreated();
}
public void Dispose()
{
_scope.Dispose();
2026-04-08 20:23:48 +02:00
}
protected HttpClient CreateAuthenticatedClient(string token = "")
{
var client = _factory.CreateClient();
if (!string.IsNullOrEmpty(token))
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
}
return client;
}
protected async Task<T?> GetAsync<T>(string url)
{
var response = await _client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<T>(_jsonOptions);
}
protected async Task<TResponse?> PostAsync<TRequest, TResponse>(string url, TRequest data)
{
var response = await _client.PostAsJsonAsync(url, data, _jsonOptions);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<TResponse>(_jsonOptions);
}
protected async Task<TResponse?> PutAsync<TRequest, TResponse>(string url, TRequest data)
{
var response = await _client.PutAsJsonAsync(url, data, _jsonOptions);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<TResponse>(_jsonOptions);
}
protected async Task DeleteAsync(string url)
{
var response = await _client.DeleteAsync(url);
response.EnsureSuccessStatusCode();
}
}