test(event-subscriber): project zaak-created notifications into the read projection (refs #7)
Failing unit + acceptance tests for the Event Subscriber's NotificationProjector: a zaken/zaak/create notification yields one INGEDIEND projection row, duplicate deliveries collapse to one row, non-zaak/non-create notifications are ignored, and a rebuild repopulates the projection from the durable notification log (PRD §8.4). The projector is a no-op stub so the tests compile and fail on the assertions; the implementation follows in the green commit. The notification log doubles as the idempotency guard and rebuild source so a rebuild needs no OpenZaak access (§8.1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
using EventSubscriber.Application;
|
||||
|
||||
namespace EventSubscriber.Tests;
|
||||
|
||||
/// <summary>Behaviour of the projector that turns NRC notifications into projection rows.
|
||||
/// The walking skeleton reacts only to a zaak being created (status INGEDIEND) and must
|
||||
/// tolerate duplicate and out-of-order deliveries (CLAUDE.md §8.6).</summary>
|
||||
public sealed class NotificationProjectorTests
|
||||
{
|
||||
private const string ZaakUrl = "http://openzaak:8000/zaken/api/v1/zaken/11111111-1111-1111-1111-111111111111";
|
||||
|
||||
private readonly InMemoryNotificationLog _log = new();
|
||||
private readonly InMemoryProjectionStore _store = new();
|
||||
|
||||
private NotificationProjector Projector() => new(_log, _store);
|
||||
|
||||
private static Notification ZaakCreated(string url = ZaakUrl)
|
||||
=> new("zaken", "zaak", "create", new Uri(url));
|
||||
|
||||
[Fact]
|
||||
public async Task creating_a_zaak_writes_one_row_with_status_ingediend()
|
||||
{
|
||||
await Projector().HandleAsync(ZaakCreated());
|
||||
|
||||
var entry = Assert.Single(await _store.AllAsync());
|
||||
Assert.Equal("11111111-1111-1111-1111-111111111111", entry.Id);
|
||||
Assert.Equal(RegistrationStatus.Ingediend, entry.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task replaying_the_same_notification_keeps_a_single_row()
|
||||
{
|
||||
var projector = Projector();
|
||||
await projector.HandleAsync(ZaakCreated());
|
||||
await projector.HandleAsync(ZaakCreated());
|
||||
|
||||
Assert.Single(await _store.AllAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task a_notification_on_another_kanaal_is_ignored()
|
||||
{
|
||||
await Projector().HandleAsync(new Notification("documenten", "enkelvoudiginformatieobject", "create", new Uri(ZaakUrl)));
|
||||
|
||||
Assert.Empty(await _store.AllAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task a_zaak_update_is_ignored_by_the_minimal_projection()
|
||||
{
|
||||
await Projector().HandleAsync(new Notification("zaken", "zaak", "update", new Uri(ZaakUrl)));
|
||||
|
||||
Assert.Empty(await _store.AllAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task rebuild_repopulates_the_projection_from_the_notification_log()
|
||||
{
|
||||
var projector = Projector();
|
||||
await projector.HandleAsync(ZaakCreated());
|
||||
await _store.ClearAsync();
|
||||
Assert.Empty(await _store.AllAsync());
|
||||
|
||||
await projector.RebuildAsync();
|
||||
|
||||
var entry = Assert.Single(await _store.AllAsync());
|
||||
Assert.Equal(RegistrationStatus.Ingediend, entry.Status);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user