MockMvc
String Validation
Response Body
Testing in Spring
Java

How to check String in response body with mockMvc

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

MockMvc lets you test Spring MVC endpoints without starting a real server. One of the most common assertions is checking whether the response body equals a string or contains a particular fragment.

The exact matcher depends on what you want to prove. For plain text responses, content().string(...) is usually enough. For JSON responses, checking one fragment can work, but structure-aware assertions are often better.

Exact Match Versus Partial Match

If the whole response body should match exactly, use content().string("..."). If you only care that the body contains some text, combine it with a Hamcrest matcher such as containsString.

Here is a minimal controller and test:

java
1import static org.hamcrest.Matchers.containsString;
2import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
3import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
4import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
5
6import org.junit.jupiter.api.Test;
7import org.springframework.beans.factory.annotation.Autowired;
8import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
9import org.springframework.http.MediaType;
10import org.springframework.test.web.servlet.MockMvc;
11import org.springframework.web.bind.annotation.GetMapping;
12import org.springframework.web.bind.annotation.RestController;
13
14@RestController
15class GreetingController {
16    @GetMapping(value = "/greet", produces = MediaType.TEXT_PLAIN_VALUE)
17    String greet() {
18        return "Hello, MockMvc!";
19    }
20}
21
22@WebMvcTest(GreetingController.class)
23class GreetingControllerTest {
24    @Autowired
25    private MockMvc mockMvc;
26
27    @Test
28    void responseContainsExpectedText() throws Exception {
29        mockMvc.perform(get("/greet"))
30                .andExpect(status().isOk())
31                .andExpect(content().string(containsString("MockMvc")));
32    }
33
34    @Test
35    void responseMatchesExactly() throws Exception {
36        mockMvc.perform(get("/greet"))
37                .andExpect(status().isOk())
38                .andExpect(content().string("Hello, MockMvc!"));
39    }
40}

The first test is flexible. The second is strict and will fail if whitespace, punctuation, or formatting changes.

Reading the Body as Text

If you need more control than a matcher provides, you can inspect the response manually:

java
1import static org.assertj.core.api.Assertions.assertThat;
2import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
3
4import org.junit.jupiter.api.Test;
5import org.springframework.beans.factory.annotation.Autowired;
6import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
7import org.springframework.test.web.servlet.MockMvc;
8import org.springframework.test.web.servlet.MvcResult;
9
10@WebMvcTest(GreetingController.class)
11class ManualBodyAssertionTest {
12    @Autowired
13    private MockMvc mockMvc;
14
15    @Test
16    void responseBodyCanBeReadDirectly() throws Exception {
17        MvcResult result = mockMvc.perform(get("/greet")).andReturn();
18        String body = result.getResponse().getContentAsString();
19
20        assertThat(body).startsWith("Hello");
21    }
22}

This is useful when the assertion is too custom for a single built-in matcher. You can normalize whitespace, split lines, or run several assertions against the same body.

Plain Text Versus JSON

Checking raw text is fine for plain text endpoints, HTML fragments, or simple error messages. For JSON, substring checks can be brittle because formatting changes may break the test even when the JSON content is still correct.

For JSON responses, prefer jsonPath when possible:

java
1mockMvc.perform(get("/api/user/42"))
2        .andExpect(status().isOk())
3        .andExpect(content().contentType("application/json"))
4        .andExpect(jsonPath("$.name").value("Alice"));

That assertion is more precise than checking whether the body merely contains "Alice".

When a Substring Assertion Is the Right Tool

There are still many cases where containsString is exactly what you want. Server-rendered HTML pages, plain-text health endpoints, and error messages often contain extra markup or context that would make an exact-string assertion too fragile.

For example, if an HTML response includes a heading, a timestamp, and a footer, asserting the full body would couple the test to layout details. Checking that the key phrase is present is often the better balance between accuracy and maintainability.

The same idea applies to validation errors. If the response says "email is required" inside a larger payload, the test should usually assert that the message appears, not that the entire response body matches one exact line.

Common Pitfalls

  • Using exact-string assertions for responses that contain dynamic data such as timestamps or generated IDs.
  • Checking raw JSON text with containsString when a jsonPath assertion would be more stable.
  • Forgetting character encoding when the response contains non-ASCII text and you read it manually.
  • Asserting only the body and ignoring the status code or content type, which can hide real failures.

Summary

  • Use content().string("...") when the entire response must match exactly.
  • Use content().string(containsString("...")) when only part of the body matters.
  • Read the body with getContentAsString() if you need custom assertions.
  • Prefer jsonPath for JSON payloads instead of substring checks.
  • Combine body assertions with status and content-type checks for stronger tests.

Course illustration
Course illustration

All Rights Reserved.