package com.ankurm.cqrsdemo; import com.ankurm.cqrsdemo.command.OrderCommandController.LineRequest; import com.ankurm.cqrsdemo.command.OrderCommandController.PlaceOrderRequest; import com.ankurm.cqrsdemo.command.OrderCommandController.PlaceOrderResponse; import com.ankurm.cqrsdemo.query.OrderSummary; import org.junit.jupiter.api.Test; import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; import org.springframework.boot.resttestclient.TestRestTemplate; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.ResponseEntity; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; /** * Default profile: no {@code async-projection}, so {@link com.ankurm.cqrsdemo.read.SyncOrderSummaryProjection} * is active. The projection's simulated write delay (300ms, see {@code application.properties}) * runs on the same thread that is about to answer the command's HTTP request, so it shows up * directly in how long {@code POST /orders} takes -- and because of that, the read model is * already correct the instant the command returns, with no waiting required. */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureTestRestTemplate class SyncProfileLatencyTest { @org.springframework.beans.factory.annotation.Autowired private TestRestTemplate rest; @Test void placingAnOrderTakesAtLeastTheSimulatedProjectionDelayAndTheReadModelIsImmediatelyConsistent() { PlaceOrderRequest request = new PlaceOrderRequest("Priya", List.of(new LineRequest("USB-C-CABLE", 2, 1299), new LineRequest("USB-C-HUB", 1, 4999))); long start = System.currentTimeMillis(); ResponseEntity placed = rest.postForEntity("/orders", request, PlaceOrderResponse.class); long elapsedMs = System.currentTimeMillis() - start; String orderId = placed.getBody().orderId(); System.out.println("POST /orders (sync profile) took " + elapsedMs + " ms, orderId=" + orderId); assertThat(elapsedMs).isGreaterThanOrEqualTo(300L); ResponseEntity summary = rest.getForEntity("/order-summaries/" + orderId, OrderSummary.class); System.out.println("Immediately after POST returned, GET /order-summaries/" + orderId + " -> status=" + summary.getStatusCode() + ", body=" + summary.getBody()); assertThat(summary.getBody()).isNotNull(); assertThat(summary.getBody().totalCents()).isEqualTo(2 * 1299 + 4999); assertThat(summary.getBody().status()).isEqualTo("PLACED"); } }