patternjavaspringTip
MockMvc: verify JSON response structure with jsonPath
Viewed 0 times
MockMvcjsonPathandExpectJSON assertioncontroller testWebMvcTest
Problem
Tests that assert the full serialized JSON string are brittle — whitespace differences, field ordering, and unrelated additions break the test. A better approach asserts specific fields and structures.
Solution
Use MockMvc with jsonPath assertions:
For complex assertions, deserialize the response:
mockMvc.perform(post("/orders")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated())
.andExpect(header().string("Location", matchesPattern("/orders/\\d+")))
.andExpect(jsonPath("$.id").isNumber())
.andExpect(jsonPath("$.status").value("PENDING"))
.andExpect(jsonPath("$.items").isArray())
.andExpect(jsonPath("$.items", hasSize(2)))
.andExpect(jsonPath("$.items[0].productId").value("SKU-001"))
.andDo(print()); // print request/response for debuggingFor complex assertions, deserialize the response:
String body = result.andReturn().getResponse().getContentAsString();
OrderResponse order = objectMapper.readValue(body, OrderResponse.class);
assertThat(order.total()).isEqualByComparingTo("49.99");Why
JSONPath expressions navigate the JSON tree without caring about unrelated fields. Tests remain valid when new fields are added to the response, and the assertion intent is clear.
Gotchas
- jsonPath requires the json-path and json-path-assert libraries — included transitively with spring-boot-starter-test
- andDo(print()) is invaluable during development but should be removed from committed test code
- MockMvc does not exercise the real network stack; use @SpringBootTest with TestRestTemplate or WebTestClient for full HTTP integration tests
Revisions (0)
No revisions yet.