skip to content

MockMvc API

MockMvc performs a request against the Spring MVC stack without a server and matches on status, headers and content. Interviewers ask about standalone versus context setup, since one tests the controller and the other tests your configuration too.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is MockMvc and how do you write a basic controller test with perform and andExpect?

level: juniorimportance: must knowfreq 80%

answer

  1. No socket — DispatcherServlet in-memory
  2. perform(get(...)).andExpect(status().isOk())
  3. RequestBuilders / perform / ResultMatchers
  4. andDo(print()), andReturn() -> MvcResult
  5. @WebMvcTest gives you a MockMvc

basics

~10 s

MockMvc lets you test Spring MVC controllers without starting a real HTTP server. You call mockMvc.perform(get("/url")) to send a fake request, then chain andExpect(status().isOk()) to assert on the response.

solid answer

~30 s

MockMvc is Spring's server-side test harness for MVC controllers. It runs the full DispatcherServlet flow (mapping, argument resolution, the controller method, message converters, exception handling) in-process, with no socket or real servlet container, so it's fast and deterministic. You build requests with MockMvcRequestBuilders (get, post, put, delete, multipart), execute them via mockMvc.perform(...), and assert with MockMvcResultMatchers chained through andExpect — status().isOk(), content().json(...), jsonPath(...), header(...). andDo(print()) dumps the request/response for debugging, and andReturn() hands back the MvcResult for custom assertions. You obtain a MockMvc from @WebMvcTest (auto-configured, sliced) or build one manually with MockMvcBuilders.standaloneSetup / webAppContextSetup.

code

java · 19 lines
java
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired MockMvc mockMvc;
    @MockitoBean UserService userService;

    @Test
    void returnsUser() throws Exception {
        when(userService.find(42L)).thenReturn(new User(42L, "Ada"));

        mockMvc.perform(get("/users/{id}", 42))
               .andDo(print())
               .andExpect(status().isOk())
               .andExpect(content().contentType(MediaType.APPLICATION_JSON))
               .andExpect(jsonPath("$.name").value("Ada"));
    }
}
// static imports: MockMvcRequestBuilders.get,
// MockMvcResultMatchers.*, MockMvcResultHandlers.print

go deeper

for a junior

Must know perform + andExpect(status().isOk()) and that no server starts.

for a middle

Should wire it via @WebMvcTest, mock collaborators, assert JSON with jsonPath.

for a senior

Explains the full DispatcherServlet pipeline runs in-memory and where filters fit.

for a principal

Frames MockMvc vs WebTestClient/TestRestTemplate trade-offs across the test pyramid.

**MockMvc** is the core class in Spring's `spring-test` module for testing Spring MVC (web) controllers *without a running servlet container* (no Tomcat, no TCP socket, no real network). Instead it drives a `MockHttpServletRequest`/`MockHttpServletResponse` pair through the actual `DispatcherServlet`, so the full server-side request-processing pipeline runs in-memory: handler mapping (which `@RequestMapping`/`@GetMapping` method matches), argument resolution (`@RequestParam`, `@PathVariable`, `@RequestBody` via `HttpMessageConverter`), the controller invocation, return-value handling, `@ExceptionHandler`/`@ControllerAdvice`, and view/serialization. Because there is no socket, tests are fast and deterministic, but you are testing the *Spring MVC layer*, not real HTTP. **The three moving parts:** 1. **`MockMvcRequestBuilders`** — static factory for requests: `get(uri)`, `post(uri)`, `put`, `delete`, `patch`, `multipart(uri)`. You fluently add `.param(...)`, `.header(...)`, `.contentType(MediaType.APPLICATION_JSON)`, `.content(jsonString)`, `.accept(...)`, `.cookie(...)`. Typically static-imported. 2. **`mockMvc.perform(RequestBuilder)`** — executes the request and returns a `ResultActions`. 3. **`MockMvcResultMatchers`** — static factory for assertions: `status()`, `content()`, `header()`, `jsonPath(...)`, `redirectedUrl(...)`, `view()`, `model()`. Each `andExpect(matcher)` verifies one thing; failures throw `AssertionError`. **A minimal test flow:** ```java mockMvc.perform(get("/users/42")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.name").value("Ada")); ``` **Obtaining a MockMvc instance** — three routes: - **`@WebMvcTest(MyController.class)`** auto-configures a sliced MockMvc (only the web layer; you mock collaborators with `@MockitoBean`). - **`MockMvcBuilders.webAppContextSetup(wac)`** builds one from a full `WebApplicationContext` (usually with `@SpringBootTest` + `@AutoConfigureMockMvc`, or `@WebMvcTest` does this under the hood). - **`MockMvcBuilders.standaloneSetup(controllerInstance)`** registers controllers manually with no Spring context. **Chaining helpers:** `andDo(print())` (from `MockMvcResultHandlers`) prints the full request/response — invaluable when an assertion fails. `andReturn()` returns the `MvcResult` so you can pull `getResponse().getContentAsString()` for custom parsing. **Gotchas:** MockMvc does not run a real container, so servlet filters run only if explicitly registered (`.addFilters(...)` in standalone; auto-added under `@WebMvcTest`/`@AutoConfigureMockMvc`). It does not test actual HTTP semantics, connection handling, or real deserialization at the socket level — for that use `WebTestClient` or `TestRestTemplate` with `@SpringBootTest(webEnvironment=RANDOM_PORT)`. Assertions stop at the first failing `andExpect` unless you use `andExpectAll(...)`.

  • Does MockMvc start a real HTTP server or open a port?
    No. It drives the DispatcherServlet in-process using mock request/response objects. There is no socket. For real HTTP use TestRestTemplate or WebTestClient with a RANDOM_PORT @SpringBootTest.
  • Why does perform throw a checked Exception?
    perform(...) declares throws Exception, so JUnit test methods typically declare throws Exception too. It surfaces any exception from the dispatch pipeline that wasn't handled.

context

open as a page

How do you assert on status, headers, and body with MockMvcResultMatchers, and how do content() and jsonPath() differ?

level: middleimportance: must knowfreq 70%

basics

~10 s

Chain andExpect with MockMvcResultMatchers: status().isOk() for the code, header().string("Location", "/x") for headers, and content().string(...)/content().json(...) or jsonPath("$.field").value(...) for the body.

open as a page

What is the difference between MockMvcBuilders.standaloneSetup and webAppContextSetup, and when would you use each?

level: seniorimportance: must knowfreq 60%

basics

~20 s

standaloneSetup registers controllers manually with no Spring context — fast and focused but you wire everything yourself. webAppContextSetup builds MockMvc from a loaded WebApplicationContext, so real beans, filters, advice, and config apply — more realistic but heavier.

open as a page

How do you test a file-upload (multipart) endpoint with MockMvc?

level: middleimportance: should knowfreq 45%

basics

~10 s

Use MockMvcRequestBuilders.multipart("/upload") and attach a MockMultipartFile with .file(...). The MockMultipartFile's first constructor arg (the name) must match the controller's @RequestParam / @RequestPart name.

open as a page

When do you use andReturn/MvcResult, how do you test async controller methods, and what are MockMvc's fundamental limitations?

level: principalimportance: should knowfreq 35%

basics

~20 s

andReturn() gives you the MvcResult for custom assertions on the raw response. For async endpoints (returning DeferredResult/Callable/CompletableFuture), first andExpect(request().asyncStarted()), then re-dispatch with asyncDispatch(mvcResult). MockMvc's key limit: it runs the DispatcherServlet in-memory, not a real HTTP server.

open as a page