test(acl): ACL integration test against real OpenZaak (closes #46) #54
Reference in New Issue
Block a user
Delete Branch "test/46-acl-openzaak-integration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
S-04a — the deferred S-04 acceptance criterion: an integration test that drives the real
OpenZaakGatewayagainst a real OpenZaak, exercising the live ZGW JWT auth andPOST /zaken/api/v1/zakencontract (CRS headers, default-fill, the returned zaak URL) that the stubbed-HttpMessageHandlerunit tests cannot.Closes #46
Closes #53 (adr-proposal — recorded as ADR-0006)
Closes #55 (CI execution — folded into this PR)
Approach (ADR-0006)
The test targets the compose stack, not a Testcontainers graph: Testcontainers .NET has no docker-compose support (it would mean hand-rolling the 5-service stack in C#), and the test can't be hermetic anyway — a published zaaktype pulls in the external
selectielijst.openzaak.nlreference API. No new NuGet dependency is added.Acl.IntegrationTests([Trait("Category","Integration")]) is excluded from the fast lanes:make unitfiltersCategory!=Integrationand Stryker is pinned toAcl.Tests.make integration(→infra/run-integration.sh) owns the stack lifecycle: up → seed → test → always tear down.seed_catalogus.pygains anOZ_PUBLISH=1path that adds the relations OpenZaak's publish requires (two statustypen, a roltype, and a resultaattype with its Selectielijst procestype matched onto the zaaktype). The default seed (ADR-0002) still leaves the zaaktype a concept.It caught a real bug
Against real OpenZaak the gateway POST returned
400:JsonContentstreams the body without aContent-Length, so .NET frames itTransfer-Encoding: chunked, which OpenZaak's uwsgi rejects. A stub handler accepts either framing, so only the integration test surfaced it. Fixed by buffering the body; guarded in the fast lane by a unit test asserting aContent-Lengthis sent (which also keeps the Stryker score above the ratchet).Running it on CI
A process on the hosted runner can't reach the stack's published ports (sibling containers via the host daemon — gitea-actions-gotchas.md §5), so
infra/run-integration.shruns both the seed and the test as containers joined to the OpenZaak network, reaching it by container IP (a single-label host likeopenzaakisn't URL-valid for OpenZaak's ownURLValidator; an IPv4 literal is). Code is delivered by image build (services/acl/Dockerfile.integration) anddocker cp— never bind-mounts. dotnet runs inside the test image, so theintegrationCI job needs only Docker.Definition of Done
test(acl)→ greenfix(acl)).refs #46).docker compose upsmoke unaffected (full stack untouched).Notes for reviewers
integrationjob needs egress toselectielijst.openzaak.nl(from the OpenZaak + seed containers) — the one network touchpoint, overridable viaOZ_SELECTIELIJST. Documented in ADR-0006.OpenZaakGatewayproduction behaviour (buffers before send) — the actual fix the new test drove; worth a careful look.infra/run-integration.shuses only plain docker primitives (run/create/cp/build) so it works identically under docker compose (CI) and podman-compose (local).