Add TUnit-based unit and integration tests for backend

Set up YesChef.Api.UnitTests and YesChef.Api.IntegrationTests projects
running on TUnit + Microsoft.Testing.Platform. Integration tests use a
single Postgres 17 Testcontainer per session and clone a migrated
template database per test (`CREATE DATABASE … TEMPLATE …`) so tests
remain fully isolated and run in parallel without replaying migrations
each time.

Test-author DX is built around fluent entity builders, a TestDataFactory
for common scenarios, and a two-level base hierarchy
(IntegrationTest / AuthenticatedIntegrationTest) whose `[Before(Test)]`
hooks stand up the per-test database, app factory, default user, and
authenticated HttpClient — leaving each test body focused on the action
under test.

Adds src/backend/global.json to opt `dotnet test` into MTP mode on the
.NET 10 SDK, and updates CLAUDE.md with how to run the tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Josh Rogers
2026-05-06 20:56:29 -05:00
parent 7ca2dc46d9
commit 76e8de9484
23 changed files with 1199 additions and 0 deletions
@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Identity;
using YesChef.Api.Data;
using YesChef.Api.Entities;
namespace YesChef.Api.IntegrationTests.Builders;
public sealed class UserBuilder
{
private string _name = $"user-{Guid.NewGuid():N}"[..16];
private string _password = "correct-horse-battery-staple";
public UserBuilder Named(string name) { _name = name; return this; }
public UserBuilder WithPassword(string password) { _password = password; return this; }
public string PlaintextPassword => _password;
public User Build()
{
var user = new User { Name = _name, PasswordHash = "" };
user.PasswordHash = new PasswordHasher<User>().HashPassword(user, _password);
return user;
}
public async Task<User> PersistAsync(YesChefDb db)
{
var user = Build();
db.Users.Add(user);
await db.SaveChangesAsync();
return user;
}
}