skip to content

MockMvcTester (AssertJ)

MockMvcTester wraps MockMvc in a fluent AssertJ API, so assertions read as assertThat(...).hasStatusOk().bodyJson(). Worth knowing as the current style, and as evidence you follow recent Spring releases.

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

questions

5

What is MockMvcTester in Spring 6.2, and how do you use it to assert a controller returns 200 with a JSON body?

level: juniorimportance: must knowfreq 70%

answer

  1. Spring 6.2 fluent AssertJ over MockMvc
  2. assertThat(mvc.get().uri(...)).hasStatusOk()
  3. create(mockMvc) / from(context) / of(controllers)
  4. bodyJson().extractingPath("$.x")
  5. still mock servlet stack, no real server

basics

~10 s

MockMvcTester (Spring 6.2) is a fluent, AssertJ-based wrapper around MockMvc. You perform a request like mvc.get().uri("/x") and pass it to AssertJ's assertThat(...), then chain checks such as .hasStatusOk() and .bodyJson().

solid answer

~40 s

MockMvcTester, added in Spring Framework 6.2, is a fluent facade over MockMvc that integrates with AssertJ instead of MockMvc's older Hamcrest-style ResultMatchers. You build a request with a fluent builder (mvc.get().uri("/users/1")), wrap it in AssertJ's assertThat(...), and chain readable assertions: .hasStatusOk(), .hasContentType(MediaType.APPLICATION_JSON), and .bodyJson() to assert JSON content via JSONPath. It still drives the same mock servlet stack (DispatcherServlet) as classic MockMvc — no real HTTP or running server. You create it with MockMvcTester.create(existingMockMvc) or MockMvcTester.from(webApplicationContext). Under Spring Boot 3.4+, a MockMvcTester bean is auto-configured with @WebMvcTest / @AutoConfigureMockMvc, so you can inject it directly. It gives more readable failures and better IDE completion than perform(...).andExpect(...).

code

java · 17 lines
java
import static org.assertj.core.api.Assertions.assertThat;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.assertj.MockMvcTester;

class UserControllerTests {
    private final MockMvcTester mvc; // e.g. MockMvcTester.create(mockMvc) or injected

    UserControllerTests(MockMvcTester mvc) { this.mvc = mvc; }

    void returnsUser() {
        assertThat(mvc.get().uri("/users/{id}", 1))
                .hasStatusOk()
                .hasContentType(MediaType.APPLICATION_JSON)
                .bodyJson()
                .extractingPath("$.name").isEqualTo("Alice");
    }
}

go deeper

for a junior

Know it's the new fluent AssertJ way to test controllers; recognize assertThat(mvc.get().uri(...)).hasStatusOk().

for a middle

Know the create/from/of factories and the main body/status/header assertions, plus Boot 3.4 auto-config.

for a senior

Contrast with classic MockMvc, explain lazy exchange, exception capture, and JSON assertions.

for a principal

Advise on adoption strategy, migration from perform(...), and where MockMvcTester fits vs WebTestClient in a testing pyramid.

## What it is **MockMvcTester** is a class introduced in **Spring Framework 6.2** that provides a **fluent, AssertJ-flavored** API on top of the existing **MockMvc** testing infrastructure. MockMvc lets you test Spring MVC controllers without starting a real web server: it wires up the `DispatcherServlet` and processes mock `HttpServletRequest`/`HttpServletResponse` objects in-process. The classic MockMvc API reads like `mockMvc.perform(get("/x")).andExpect(status().isOk())` and uses Hamcrest `Matcher`s. MockMvcTester keeps the same underlying engine but exposes it through **AssertJ**, the fluent assertion library (`assertThat(...).hasXxx()`), which most teams already use. ## Creating it - `MockMvcTester.create(MockMvc mockMvc)` — wrap an existing `MockMvc` instance you already built. - `MockMvcTester.from(WebApplicationContext context)` — build from the full web application context (optionally passing a customizer to tweak the underlying builder). - `MockMvcTester.of(controllers...)` — a **standalone** setup that registers only the given controller instances (no full context), analogous to `MockMvcBuilders.standaloneSetup(...)`. - Under **Spring Boot 3.4+**, `@WebMvcTest` and `@AutoConfigureMockMvc` auto-configure a `MockMvcTester` bean, so you just `@Autowired MockMvcTester mvc`. ## Performing a request You start with an HTTP-method builder: `mvc.get()`, `mvc.post()`, `mvc.put()`, `mvc.delete()`, or `mvc.method(HttpMethod.PATCH)`. You then configure it fluently: `.uri("/users/{id}", 1)`, `.param("q", "spring")`, `.contentType(MediaType.APPLICATION_JSON)`, `.content(json)`, `.accept(...)`, `.header(...)`, `.cookie(...)`. The resulting builder is special: it implements AssertJ's `AssertProvider`, so passing it to `assertThat(...)` **triggers the request lazily** and returns an `MvcTestResultAssert`. You can also call `.exchange()` explicitly to get an `MvcTestResult` and assert on it later. ## Common assertions - **Status:** `.hasStatusOk()`, `.hasStatus(HttpStatus.CREATED)`, `.hasStatus(201)`, `.hasStatus2xxSuccessful()`, `.hasStatus4xxClientError()`. - **Headers / content type:** `.hasContentType(MediaType.APPLICATION_JSON)`, `.headers().hasValue("X-Trace", "...")`. - **Body as text:** `.body().asString().contains("...")` (or `.hasBodyTextEqualTo(...)`). - **Body as JSON:** `.bodyJson()` returns a JSON assert you can drive with JSONPath: `.extractingPath("$.name").isEqualTo("Alice")`, `.hasPathSatisfying("$.id", v -> v.assertThat().isNotNull())`, or compare whole documents with `.isLenientlyEqualTo(...)` / `.isStrictlyEqualTo(...)`. - **Redirects / views (for server-rendered MVC):** `.hasRedirectedUrl(...)`, `.hasForwardedUrl(...)`, `.hasViewName(...)`, `.model()`. ## Why use it - **Readability + IDE completion:** AssertJ chains discover methods via autocomplete; failure messages are richer than Hamcrest. - **Consistency:** if your project already asserts with AssertJ, tests read uniformly. - **Exception capture:** unlike classic MockMvc (which rethrows an unresolved handler exception out of `perform`), MockMvcTester captures it so you can assert on the failure (`.hasFailed()`, `.failure()`). ## Gotchas - It is **not** a real HTTP client — still the mock servlet stack; use `WebTestClient` or `TestRestClient`/`RestAssured` against a running server for full-stack tests. - `.bodyJson()` needs a JSONPath/JSON library on the classpath (present via spring-test / Spring Boot test starter). - The request runs **lazily** on `assertThat(...)` or `.exchange()`; forgetting to assert means the request never executes.

  • Does MockMvcTester start a real HTTP server?
    No. It drives the same in-memory mock servlet stack (DispatcherServlet) as classic MockMvc — no socket, no running server. For real HTTP use WebTestClient or a client against a @SpringBootTest(webEnvironment=RANDOM_PORT) server.
  • How does it differ from mockMvc.perform(...).andExpect(...)?
    Same engine, different assertion style: MockMvcTester uses fluent AssertJ (assertThat(...).hasStatusOk()) instead of Hamcrest ResultMatchers, giving better IDE completion, richer failure messages, and the ability to capture and assert on unresolved exceptions.

saying these in an interview costs you the question

  • Thinking MockMvcTester makes real HTTP calls / starts a server
  • Confusing it with WebTestClient (reactive/real-HTTP)
  • Claiming it still uses Hamcrest matchers

context

open as a page

What are the ways to create a MockMvcTester, and how do create(), from(), and of() differ?

level: middleimportance: should knowfreq 45%

basics

~10 s

Three factories: MockMvcTester.create(mockMvc) wraps an existing MockMvc; MockMvcTester.from(webApplicationContext) builds one from the full context; MockMvcTester.of(controllers...) does a standalone setup with just the given controllers. Spring Boot 3.4+ also auto-configures an injectable bean.

open as a page

How do you assert on a JSON response body with MockMvcTester's bodyJson()?

level: seniorimportance: should knowfreq 50%

basics

~10 s

Call .bodyJson() after a request to get a JSON assert. Use .extractingPath("$.field") with JSONPath to check individual values, .convertTo(Type.class) to deserialize, or .isLenientlyEqualTo(...)/.isStrictlyEqualTo(...) to compare whole documents.

open as a page

How does MockMvcTester handle a controller exception that no @ExceptionHandler resolves, and how does that differ from classic MockMvc?

level: seniorimportance: should knowfreq 35%

basics

~20 s

MockMvcTester captures an unresolved handler exception in the result instead of throwing it out of the call. You assert on it with .hasFailed() and .failure(). Classic MockMvc rethrows the exception from perform(...), so you'd need assertThatThrownBy or expectedException.

open as a page

Explain MockMvcTester's lazy exchange model and when you'd adopt it versus classic MockMvc or WebTestClient.

level: principalimportance: nice to knowfreq 25%

basics

~20 s

The request builder is an AssertJ AssertProvider, so the request only runs when you call assertThat(...) or .exchange(). Adopt MockMvcTester for readable AssertJ servlet-slice tests; keep classic MockMvc where it's already entrenched; use WebTestClient for real-HTTP/WebFlux or full-stack tests.

open as a page