fix: v3/v4 error bodies + deterministic API version in acceptance ITs - #3
Open
emmanuelbruno wants to merge 2 commits into
Open
emmanuelbruno wants to merge 2 commits into
emmanuelbruno wants to merge 2 commits into
Conversation
v3/v4 threw entity-less WebApplicationException/NotFoundException; features assert "SKU already exists"/"Product not found" substrings; messages mirror the v5 mappers (text/plain). Evidence: GHA run 34215125166 (9 failures, empty bodies on v4).
the five tag-based @before hooks in Hooks.java overwrote VersionContext in nondeterministic order, so V3/V4 IT classes exercised a random version (usually v5); v3/v4 were never actually tested; each IT class now pins its own version.
There was a problem hiding this comment.
🟢 Approval recommended
The changes are narrowly scoped, align v3/v4 error bodies with the established v5 contract, and make acceptance tests deterministically exercise the intended API version per IT class.
Pull request overview
This PR fixes two acceptance-test-breaking defects: (1) v3/v4 404/409 responses violated the API contract by returning empty bodies, and (2) acceptance tests selected API versions nondeterministically due to multiple tag-based hooks racing to set the scenario version.
Changes:
- Ensure v3/v4 404/409
WebApplicationException/NotFoundExceptionresponses includetext/plainentities matching v5’s message wording. - Make acceptance tests deterministic by removing tag-based version hooks and introducing one per-IT-class version hook (v1–v5), then scoping glue per IT class.
File summaries
| File | Description |
|---|---|
| src/main/java/org/acme/service/v3/ProductServiceV3.java | Build 404/409 Response objects with text/plain bodies so GlobalExceptionMapper passthrough preserves error entities. |
| src/main/java/org/acme/service/v4/ProductServiceV4.java | Same as v3: ensure 404/409 exceptions carry response entities and content type. |
| src/test/java/org/acme/api/cucumber/steps/Hooks.java | Removes tag-based version setters that could overwrite each other nondeterministically. |
| src/test/java/org/acme/api/cucumber/v1/V1VersionHook.java | New per-class Cucumber @Before hook to pin VersionContext to v1. |
| src/test/java/org/acme/api/cucumber/v2/V2VersionHook.java | New per-class Cucumber @Before hook to pin VersionContext to v2. |
| src/test/java/org/acme/api/cucumber/v3/V3VersionHook.java | New per-class Cucumber @Before hook to pin VersionContext to v3. |
| src/test/java/org/acme/api/cucumber/v4/V4VersionHook.java | New per-class Cucumber @Before hook to pin VersionContext to v4. |
| src/test/java/org/acme/api/cucumber/v5/V5VersionHook.java | New per-class Cucumber @Before hook to pin VersionContext to v5. |
| src/test/java/org/acme/api/cucumber/v1/CatalogV1AcceptanceIT.java | Adds v1 glue package so only the v1 pinning hook runs for this IT. |
| src/test/java/org/acme/api/cucumber/v2/CatalogV2AcceptanceIT.java | Adds v2 glue package so only the v2 pinning hook runs for this IT. |
| src/test/java/org/acme/api/cucumber/v3/CatalogV3AcceptanceIT.java | Adds v3 glue package so only the v3 pinning hook runs for this IT. |
| src/test/java/org/acme/api/cucumber/v4/CatalogV4AcceptanceIT.java | Adds v4 glue package so only the v4 pinning hook runs for this IT. |
| src/test/java/org/acme/api/cucumber/v5/CatalogV5AcceptanceIT.java | Adds v5 glue package so only the v5 pinning hook runs for this IT. |
Review details
- Files reviewed: 13/13 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects fixed
1. v3/v4 error responses had empty bodies (API contract violation).
ProductServiceV3/ProductServiceV4threw entity-lessWebApplicationException/NotFoundExceptionfor 409/404, andGlobalExceptionMapperpassesWebApplicationExceptions through untouched — so clients got empty bodies. The shared Cucumber scenarios assertcontainsString("SKU already exists")/containsString("Product not found")(only v5's plain-exception path producedtext/plainbodies viaConflictMapper/NotFoundMapper).Evidence: GHA run 34215125166 — arm64 leg:
Tests run: 77, Failures: 9, all 9 =the error message should containon the 409-create / 404-get / 404-delete scenarios.2. Non-deterministic API version in the acceptance ITs (v3/v4 were never actually tested).
Hooks.javahad five tag-based@Beforehooks (@v1…@v5) each overwriting the scenario-scopedVersionContext. The shared catalog scenarios are tagged@v3 @v4 @v5, so in any run three hooks fired in nondeterministic order and the last one won — eachCatalogV*AcceptanceITexercised a random version (usually v5, hence "previously green"). In run 34215125166 all three of V3/V4/V5 classes landed on v3/v4 and failed identically.Changes
Commit 1 —
fix: return error bodies for v3/v4 409/404 responses (API contract)ProductServiceV3(get-404, create-409; delete delegates to get) andProductServiceV4(get-404, create-409, delete-404) now throwResponse.status(...).entity(...).type(text/plain).build()with wording mirroring the v5 mappers exactly:"Product SKU already exists: <sku>"(409) and"Product not found: <sku>"(404).GlobalExceptionMapper, the v5 mappers, and all v5 behavior are untouched.Commit 2 —
test: pin API version deterministically per acceptance IT classDeleted the five tag-based version setters from
Hooks.javaand added one tagless@Beforeglue hook per IT class (V1VersionHook…V5VersionHookinorg.acme.api.cucumber.v1…v5), each IT's@CucumberOptions.gluenow includes its own package. Exactly one version setter can fire per IT class, so each class deterministically exercises its own version.Note: the spec initially assumed only V3/V4/V5 IT classes exist, but
CatalogV1AcceptanceIT/CatalogV2AcceptanceITalso exist (features tagged@v1/@v2); they get the same deterministic per-class treatment (V1/V2 hooks), so all five tag hooks are replaced 1:1.Verification
CI on head
3f977b7— run https://github.com/ebpro/notebook-java-rest-sample-quarkus/actions/runs/34233437148 — success (~2m15s).Tests run: 77, Failures: 0, Errors: 0, Skipped: 0Tests run: 7, Failures: 0, Errors: 0, Skipped: 0TestDebugFiltershows 0 cross-version hits — every class hit only its own version:CatalogV1AcceptanceIT→/api/v1/...(2/2)CatalogV2AcceptanceIT→/api/v2/...(2/2)CatalogV3AcceptanceIT→/api/v3/...(4/4)CatalogV4AcceptanceIT→/api/v4/...(4/4)CatalogV5AcceptanceIT→/api/v5/...(6/6)34215125166(empty bodies) now PASS, e.g. v3/v4 409 →Product SKU already exists: TV-1, v3/v4 404 →Product not found: NON-EXISTENT../mvnw -B verifywas not run (local Testcontainers/podman socket unavailable for this user); the CI run above is the verification gate.