tests: fix integration test setup

This commit is contained in:
Stevan Freeborn
2026-02-01 11:31:46 -06:00
parent bf7b1b3fc8
commit e479ba4c8a
3 changed files with 55 additions and 30 deletions
@@ -1,39 +1,39 @@
using FiscalOS.API.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace FiscalOS.API.Tests.Integration;
public abstract class IntegrationTest(TestApi testApi) : IClassFixture<TestApi>, IAsyncLifetime
{
protected TestApi TestApi { get; } = testApi;
public HttpClient Client => testApi.CreateClient();
// TODO: This seems not correct
// would need to dispose of scope
// we need to clean up the test
// database files when the test ends
protected DbContext TestDbContext
public async ValueTask InitializeAsync()
{
get
await ExecuteDbContextAsync(static async context =>
{
var scopeFactory = TestApi.Services.GetRequiredService<IServiceScopeFactory>();
var scope = scopeFactory.CreateScope();
return scope.ServiceProvider.GetRequiredService<AppDbContext>();
}
await context.Database.EnsureCreatedAsync();
});
}
public ValueTask InitializeAsync()
protected async Task ExecuteDbContextAsync(Func<DbContext, Task> action)
{
return new(TestDbContext.Database.EnsureCreatedAsync());
await using var scope = testApi.Services.CreateAsyncScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await action(context);
}
public ValueTask DisposeAsync()
protected async Task<T> ExecuteDbContextAsync<T>(Func<DbContext, Task<T>> action)
{
await using var scope = testApi.Services.CreateAsyncScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await action(context);
}
public async ValueTask DisposeAsync()
{
await ExecuteDbContextAsync(static async context =>
{
await context.Database.EnsureDeletedAsync();
});
GC.SuppressFinalize(this);
return new(TestDbContext.Database.EnsureDeletedAsync());
}
}
@@ -1,3 +1,5 @@
using FiscalOS.API.Identity;
namespace FiscalOS.API.Tests.Integration;
public class LoginTests(TestApi testApi) : IntegrationTest(testApi)
@@ -6,15 +8,13 @@ public class LoginTests(TestApi testApi) : IntegrationTest(testApi)
[ClassData<LoginValidationTestCases>]
public async Task Login_WhenUserSubmitsInvalidRequest_ItShouldReturn400WithProblemDetails(LoginValidationTestCase tc)
{
var client = TestApi.CreateClient();
var req = new
{
username = tc.Username,
password = tc.Password,
};
var res = await client.PostAsJsonAsync("/login", req, TestContext.Current.CancellationToken);
var res = await Client.PostAsJsonAsync("/login", req, TestContext.Current.CancellationToken);
res.StatusCode.Should().Be(HttpStatusCode.BadRequest);
@@ -24,17 +24,39 @@ public class LoginTests(TestApi testApi) : IntegrationTest(testApi)
}
[Fact]
public async Task Login_WhenUserCredentialsAreIncorrect_ItShouldReturn401WithProblemDetails()
public async Task Login_WhenUserDoesNotExist_ItShouldReturn401WithProblemDetails()
{
var client = TestApi.CreateClient();
var req = new
{
username = "Test",
password = "@Password2",
};
var res = await client.PostAsJsonAsync("/login", req, TestContext.Current.CancellationToken);
var res = await Client.PostAsJsonAsync("/login", req, TestContext.Current.CancellationToken);
res.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task Login_WhenUserExistsButPasswordIsIncorrect_ItShouldReturn401WithProblemDetails()
{
await ExecuteDbContextAsync(static async context =>
{
context.Add(new User
{
Username = "Stevan",
});
await context.SaveChangesAsync(TestContext.Current.CancellationToken);
});
var req = new
{
username = "Stevan",
password = "@Password2",
};
var res = await Client.PostAsJsonAsync("/login", req, TestContext.Current.CancellationToken);
res.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
+3
View File
@@ -1,11 +1,14 @@
global using System.Net;
global using System.Net.Http.Json;
global using FiscalOS.API.Data;
global using FiscalOS.API.Tests.Infra;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.AspNetCore.Mvc.Testing;
global using Microsoft.EntityFrameworkCore;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging;
global using Xunit.Sdk;