Rolle im AblaufPrüft Statuscodes, Versionen, Idempotency, ETags und Fehlerverträge.
Damit ist der zentrale Pfad abgeschlossen; der Test-/Runner-Code und die vollständige Dateiliste darunter zeigen die übrigen Varianten.
package com.example.restapi;
import java.util.Map;
public final class Run5ATestRunner {
public static void main(String[] args) {
createsOrderWithIdempotencyKey();
replaysSamePostWithoutSecondSideEffect();
rejectsSameKeyWithDifferentPayload();
returnsValidationProblem();
rejectsUnsupportedVersion();
detectsIfMatchConflict();
System.out.println("RUN5A_TESTS_OK");
}
static void createsOrderWithIdempotencyKey() {
RestOrderController controller = RestApiLab.newController();
HttpResponse response = controller.handle(validPost("k-1"));
assertEquals(201, response.status(), "create status");
assertTrue(response.headers().containsKey("Location"), "location header");
assertTrue(response.body().contains("ACCEPTED"), "accepted body");
}
static void replaysSamePostWithoutSecondSideEffect() {
RestOrderController controller = RestApiLab.newController();
HttpResponse first = controller.handle(validPost("k-2"));
HttpResponse second = controller.handle(validPost("k-2"));
assertEquals(201, second.status(), "replay status");
assertEquals("true", second.headers().get("Idempotency-Replayed"), "replay header");
assertEquals(first.body(), second.body(), "same body on replay");
}
static void rejectsSameKeyWithDifferentPayload() {
RestOrderController controller = RestApiLab.newController();
controller.handle(validPost("k-3"));
HttpRequest differentPayload = HttpRequest.post("/orders", Map.of(
"X-Api-Version", "2026-01",
"Idempotency-Key", "k-3"), "customer=C-999;lines=SKU-9,1,1.00");
HttpResponse response = controller.handle(differentPayload);
assertEquals(409, response.status(), "same key different payload");
}
static void returnsValidationProblem() {
RestOrderController controller = RestApiLab.newController();
HttpRequest request = HttpRequest.post("/orders", Map.of(
"X-Api-Version", "2026-01",
"Idempotency-Key", "k-4"), "customer=;lines=SKU-1,0,19.99");
HttpResponse response = controller.handle(request);
assertEquals(400, response.status(), "validation status");
assertEquals("application/problem+json", response.headers().get("Content-Type"), "problem content type");
}
static void rejectsUnsupportedVersion() {
RestOrderController controller = RestApiLab.newController();
HttpRequest request = HttpRequest.post("/orders", Map.of(
"X-Api-Version", "2030-01",
"Idempotency-Key", "k-5"), "customer=C-100;lines=SKU-1,1,9.99");
assertEquals(406, controller.handle(request).status(), "unsupported version");
}
static void detectsIfMatchConflict() {
RestOrderController controller = RestApiLab.newController();
HttpResponse created = controller.handle(validPost("k-6"));
String location = created.headers().get("Location");
String id = location.substring("/orders/".length());
HttpRequest patch = new HttpRequest(HttpMethod.PATCH, location, Map.of(
"If-Match", "W/\"order-" + id + "-v999\"",
"X-Correlation-Id", "test-corr"), Map.of(), "");
HttpResponse response = controller.patchCustomerReference(patch, new OrderId(id), "C-OTHER");
assertEquals(412, response.status(), "etag conflict");
}
private static HttpRequest validPost(String key) {
return HttpRequest.post("/orders", Map.of(
"X-Api-Version", "2026-01",
"X-Correlation-Id", "corr-" + key,
"Idempotency-Key", key), "customer=C-100;lines=SKU-1,2,19.99|SKU-2,1,5.00");
}
private static void assertEquals(Object expected, Object actual, String message) {
if (!java.util.Objects.equals(expected, actual)) {
throw new AssertionError(message + " expected=" + expected + " actual=" + actual);
}
}
private static void assertTrue(boolean condition, String message) {
if (!condition) throw new AssertionError(message);
}
}