From 63699c3f55120000d9c75c5569eb366cf81d002a Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Tue, 14 Jul 2026 17:20:22 +0200 Subject: [PATCH] =?UTF-8?q?test(domain):=20beoordeling=20use-case=20?= =?UTF-8?q?=E2=80=94=20goedkeuren=20via=20ACL,=20afwijzen,=20idempotency?= =?UTF-8?q?=20(refs=20#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Red — the BeoordeelRegistratie use-case and BeoordelingsBesluit do not exist yet. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Big.Tests/BeoordeelRegistratieTests.cs | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 services/domain/Big.Tests/BeoordeelRegistratieTests.cs diff --git a/services/domain/Big.Tests/BeoordeelRegistratieTests.cs b/services/domain/Big.Tests/BeoordeelRegistratieTests.cs new file mode 100644 index 0000000..de51af2 --- /dev/null +++ b/services/domain/Big.Tests/BeoordeelRegistratieTests.cs @@ -0,0 +1,142 @@ +using Big.Application; +using Big.Domain; + +namespace Big.Tests; + +/// +/// The beoordeling use case (S-12): a behandelaar's decision on a registration. Goedkeuren sets the +/// zaak's final status via the ACL (§8.1) and marks the aggregate INGESCHREVEN; Afwijzen marks it +/// AFGEWEZEN in the domain (propagating a rejection to the zaak is a later sub-slice). Both are +/// idempotent so a repeated or redelivered decision is a no-op. +/// +public class BeoordeelRegistratieTests +{ + private static Registration WithZaak(string bsn = "123456782") + { + var registration = Registration.Submit(bsn); + registration.AttachZaak(FakeAclClient.DefaultZaakUrl); + return registration; + } + + [Fact] + public async Task Goedkeuren_sets_the_zaak_status_via_the_acl_and_marks_the_registration_ingeschreven() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)); + + var saved = await store.GetAsync(registration.Id); + Assert.Equal(RegistrationStatus.Ingeschreven, saved!.Status); + Assert.Equal(FakeAclClient.DefaultZaakUrl, acl.ApprovedZaakUrl); + Assert.Equal(1, acl.ApproveCallCount); + Assert.Equal(1, store.SaveCount); + } + + [Fact] + public async Task Afwijzen_marks_the_registration_afgewezen_without_calling_the_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen)); + + var saved = await store.GetAsync(registration.Id); + Assert.Equal(RegistrationStatus.Afgewezen, saved!.Status); + Assert.Equal(0, acl.ApproveCallCount); + Assert.Equal(1, store.SaveCount); + } + + [Fact] + public async Task Goedkeuren_an_in_behandeling_registration_marks_it_ingeschreven() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + registration.TakeIntoBehandeling(); + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)); + + Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status); + } + + [Fact] + public async Task Rejects_a_null_command_without_touching_the_store_or_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var handler = new BeoordeelRegistratie(store, acl); + + await Assert.ThrowsAsync(() => handler.HandleAsync(null!)); + Assert.Equal(0, acl.ApproveCallCount); + Assert.Equal(0, store.SaveCount); + } + + [Fact] + public async Task Deciding_an_unknown_registration_throws_and_does_not_call_the_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var handler = new BeoordeelRegistratie(store, acl); + + var ex = await Assert.ThrowsAsync(() => + handler.HandleAsync(new BeoordeelRegistratieCommand(RegistrationId.New(), BeoordelingsBesluit.Goedkeuren))); + Assert.Contains("No registration", ex.Message); + Assert.Equal(0, acl.ApproveCallCount); + } + + [Fact] + public async Task Goedkeuren_before_the_zaak_is_opened_throws_without_calling_the_acl() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = Registration.Submit("123456782"); // no zaak yet + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + var ex = await Assert.ThrowsAsync(() => + handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren))); + Assert.Contains("no zaak", ex.Message); + Assert.Equal(0, acl.ApproveCallCount); + } + + [Fact] + public async Task Re_goedkeuren_an_already_ingeschreven_registration_is_idempotent() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)); + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Goedkeuren)); + + Assert.Equal(1, acl.ApproveCallCount); + Assert.Equal(RegistrationStatus.Ingeschreven, (await store.GetAsync(registration.Id))!.Status); + } + + [Fact] + public async Task Re_afwijzen_an_already_afgewezen_registration_is_idempotent() + { + var store = new FakeRegistrationStore(); + var acl = new FakeAclClient(); + var registration = WithZaak(); + store.Seed(registration); + var handler = new BeoordeelRegistratie(store, acl); + + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen)); + await handler.HandleAsync(new BeoordeelRegistratieCommand(registration.Id, BeoordelingsBesluit.Afwijzen)); + + Assert.Equal(1, store.SaveCount); + Assert.Equal(RegistrationStatus.Afgewezen, (await store.GetAsync(registration.Id))!.Status); + } +}