Koto.Testing.Integration
Кирпичики для интеграционных тестов: тестовая авторизация через заголовок, проверки Eventually и продюсер raw-JSON в Kafka.
Что внутри
| Тип | Назначение |
|---|---|
AddHeaderTestAuthentication() / WithTestUser(...) | Заменяют настоящую авторизацию (JWKS, JWT) на схему по заголовкам |
Eventually.AssertAsync(...) | Проверка асинхронных эффектов опросом |
RawJsonKafkaProducer | Публикация raw-JSON интеграционных контрактов из теста |
Своей зависимости от Testcontainers у пакета нет: жизненный цикл контейнеров остаётся в вашей фикстуре, поэтому эти блоки собираются с любой раскладкой хоста — один сервис, сага из нескольких сервисов или in-memory TestServer.
Тестовая авторизация по заголовкам
Заменяет настоящую авторизацию хоста на схему, управляемую заголовками запроса X-Test-UserId / X-Test-Role, — тестам не нужно выпускать настоящие JWT:
Factory = new WebApplicationFactory<Program>().WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services => services.AddHeaderTestAuthentication());
});
using var client = Factory.CreateClient().WithTestUser(userId); // участник
using var admin = Factory.CreateClient().WithTestUser(adminId, "Admin"); // проверка роли
Eventually
Проверка асинхронных эффектов опросом — Kafka-консьюмеры, проекции, саги. Описание попадает в сообщение о таймауте, поэтому падение сразу говорит, что именно так и не случилось:
await Eventually.AssertAsync(async () =>
{
var detail = await client.GetFromJsonAsync<JsonElement>($"/meetups/{id}");
return detail.GetProperty("status").GetString() == "Settled";
}, TimeSpan.FromSeconds(45), "meetup becomes Settled");
RawJsonKafkaProducer
Публикует обычный web-cased JSON — ровно то, что выдаёт PublishIntegrationEvents (Koto.Messaging.Wolverine), — так что тест может сымитировать вышестоящий сервис или повторную доставку. Топик берётся из public const string Topic контракта (общая конвенция через IntegrationEventTopics в Koto.Application):
using var kafka = new RawJsonKafkaProducer(kafkaContainer.GetBootstrapAddress());
await kafka.PublishAsync(new UserRegisteredV1(userId, null, "Ivan", ["ru"])); // топик выводится из типа
await kafka.PublishAsync("explicit.topic", payload); // или явно