Files
mic-check/tests/api/MicCheck.Api.Tests.Unit/Webhooks/WebhookQueueTests.cs
James Wampler 4ad3285afa
All checks were successful
CI / build-and-push (push) Successful in 41s
CI / deploy-qa (push) Has been skipped
CI / smoke-qa (push) Has been skipped
Add unit tests for Audit (59% to 100%) and Webhooks (62% to 91%) namespaces
Covers AuditLogQueryService filtering/paging/actor-name join,
AuditLogResponse mapping, AuditLogsController, AuditService.LogAsync
and actor-claim resolution, WebhookResponse/WebhookDeliveryLogResponse
mapping, CreateWebhookRequestValidator, WebhookQueue, and additional
WebhookDispatcher branch coverage (scope routing, disabled webhooks,
delivery exceptions).

Excludes WebhookBackgroundService and WebhookRetryBackgroundService
from coverage: both resolve a DI-scoped concrete MicCheckDbContext via
IServiceScopeFactory, which requires a live DI container/DB per
CLAUDE.md's no-InMemory/WebApplicationFactory rule. Their query and
dispatch logic is covered by WebhookRetryTests/WebhookDispatcherTests.
2026-07-05 15:00:02 -07:00

49 lines
1.6 KiB
C#

using MicCheck.Api.Webhooks;
using NUnit.Framework;
namespace MicCheck.Api.Tests.Unit.Webhooks;
[TestFixture]
public class WebhookQueueTests
{
[Test]
public async Task WhenAnEventIsEnqueued_ThenItCanBeReadBack()
{
var queue = new WebhookQueue();
var webhookEvent = new WebhookEvent
{
EventType = WebhookEventTypes.FlagUpdated,
OrganizationId = 1,
Data = new { }
};
await queue.EnqueueAsync(webhookEvent);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await using var enumerator = queue.ReadAllAsync(cts.Token).GetAsyncEnumerator(cts.Token);
await enumerator.MoveNextAsync();
Assert.That(enumerator.Current, Is.SameAs(webhookEvent));
}
[Test]
public async Task WhenMultipleEventsAreEnqueued_ThenTheyAreReadInOrder()
{
var queue = new WebhookQueue();
var first = new WebhookEvent { EventType = WebhookEventTypes.FlagUpdated, OrganizationId = 1, Data = new { } };
var second = new WebhookEvent { EventType = WebhookEventTypes.FlagDeleted, OrganizationId = 1, Data = new { } };
await queue.EnqueueAsync(first);
await queue.EnqueueAsync(second);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await using var enumerator = queue.ReadAllAsync(cts.Token).GetAsyncEnumerator(cts.Token);
await enumerator.MoveNextAsync();
Assert.That(enumerator.Current, Is.SameAs(first));
await enumerator.MoveNextAsync();
Assert.That(enumerator.Current, Is.SameAs(second));
}
}