An MVC slice checks controller mapping and serialization with selected web components; service and database behavior need separate tests.
Spring @WebMvcTest: replace collaborators without claiming a full application
What the slice owns
A receipt controller accepts JSON, validates a command and delegates to ReceiptService. @WebMvcTest(ReceiptController.class) loads the MVC slice for that controller, not the repository graph, migration runner or remote payment client. Supply a mock service through the current Spring test bean-override mechanism and assert the HTTP contract. Standalone MockMvc assembles an even smaller setup; application-backed MockMvc can cover more wiring.
Avoid accidental production claims
An OK response from a mocked service proves the controller produced the right status and body for that supplied result. It does not prove a receipt row committed, a tenant predicate ran or an outbox entry was written. If authentication filters are part of the slice, test their behavior intentionally; if a test disables them, say so in its name. The security filter path deserves its own assertion, especially where method authorization is proxied.
Make failures concrete
Stub the service to throw the domain exception used for a missing receipt. Assert the exception advice yields the agreed status and error shape. Send malformed JSON and a validation failure. Check the service was not called for invalid input. A focused slice should start quickly and fail on mapping drift, while a separate transaction test proves storage effects. Keep one test for each boundary rather than duplicating the same mocked happy path many times.
Implementation contract
@WebMvcTest(ReceiptController.class)
class ReceiptControllerSliceTest {
@Autowired MockMvc mvc;
@MockitoBean ReceiptService receiptService;
@Test void missingReceiptReturns404() throws Exception {
when(receiptService.loadReceipt("r-47")).thenThrow(new ReceiptMissingException());
mvc.perform(get("/api/receipts/r-47"))
.andExpect(status().isNotFound());
}
}Cost and verification
A slice starts fewer beans than a full application context, reducing setup time and memory. Mock behavior must be maintained as service contracts change; false confidence is the main cost.
Common Mistakes
- Do not call a mocked controller slice a database integration test.
- Do not omit security filters while claiming authorization coverage.
- Do not duplicate a full-context test for every simple controller mapping.
Read next
Spring MockMvc standalone tests: know which HTTP layers were assembled, Spring MockMvc tests: HTTP behavior without claiming a real network test, Spring MockMvc security test: run the application filter chain, Spring command rollback test: inspect state after an injected failure, Spring TestContext cache: keep equivalent tests on one context shape.
