Clean • Professional
Controller testing in Spring Boot focuses on verifying that your REST APIs and web endpoints work correctly. It ensures that URLs, request mappings, HTTP methods, status codes, headers, and JSON responses behave exactly as expected—without testing the entire application stack.
Spring Boot provides powerful testing tools like @WebMvcTest, MockMvc, and Mockito to make controller testing fast, isolated, and reliable.
Controller Testing in Spring Boot is used to test REST APIs or web controllers without running the full application.
It ensures that your HTTP endpoints return the correct status codes, responses, and JSON data.
👉 Controller testing focuses only on the web layer, not business logic or database.
Controller testing helps you:
Controller tests are much faster than integration tests and are ideal for API-first development.
Spring Boot provides powerful tools for controller testing:
@WebMvcTest@WebMvcTest is the best and most recommended annotation for controller testing in Spring Boot. It is designed specifically to test REST controllers and web endpoints in isolation.
What @WebMvcTest Does
@WebMvcTest loads only the web layer of the application.
Included Components
Excluded Components
Because unnecessary layers are excluded, controller tests become lightweight, fast, and highly focused.
MockMvc is the heart of controller testing. It allows you to simulate HTTP requests and validate responses without starting a real server.
What You Can Do with MockMvc
GETPOSTPUTDELETE@RequestMapping and endpoint URLsController testing ensures that your REST API endpoints behave correctly.
It checks whether the controller:
Sample Controller
@RestController
@RequestMapping("/users")
publicclassUserController {
privatefinal UserService userService;
publicUserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public UsergetUser(@PathVariable Long id) {
return userService.getUserById(id);
}
}
Controller Test Using @WebMvcTest
@WebMvcTest(UserController.class)
classUserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
voidtestGetUserById()throws Exception {
Useruser=newUser(1L,"Alice");
Mockito.when(userService.getUserById(1L)).thenReturn(user);
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"));
}
}
@MockBean Is Used in Controller Tests@MockBean replaces the real service bean with a mocked version.
Benefits
In controller testing, services should always be mocked.
Example: Creating a user (common in Todo or E-Commerce APIs)
@Test
voidtestCreateUser()throws Exception {
Useruser=newUser(1L,"John");
Mockito.when(userService.createUser(Mockito.any()))
.thenReturn(user);
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\\"name\\":\\"John\\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("John"));
}
In addition to GET and POST requests, it’s important to test update and delete operations in your APIs to ensure data can be modified or removed correctly.
Tests the API’s ability to update an existing resource and ensures the correct HTTP 200 OK status is returned.
mockMvc.perform(put("/users/1")
.contentType(MediaType.APPLICATION_JSON)
.content("{\\"name\\":\\"Updated Name\\"}"))
.andExpect(status().isOk());
Verifies that the API successfully deletes a resource and returns the correct HTTP 204 No Content response.
mockMvc.perform(delete("/users/1"))
.andExpect(status().isNoContent());
Controller tests should verify how your API handles invalid input. This ensures that:
Example: Testing a POST Request with Invalid Data
@Test
voidtestValidationError()throws Exception {
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\\"name\\":\\"\\"}"))
.andExpect(status().isBadRequest());
}
When testing controllers, it’s important to not only check status codes and response body, but also HTTP headers. Headers can contain important metadata such as Content-Type, Location, caching info, or custom headers.
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(header().exists("Content-Type"));
You can also check the exact value of a header:
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(header().string("Content-Type","application/json"));
.header().string() verifies the header value matches exactly.X-Rate-Limit or Location.For Spring Security–protected endpoints, use @WithMockUser.
@WithMockUser(roles = "ADMIN")
@Test
voidtestAdminAccess()throws Exception {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isOk());
}
This allows you to:
@WebMvcTestAvoid @WebMvcTest when:
👉 Use @SpringBootTest in these cases.
| Feature | Controller Testing | Integration Testing |
|---|---|---|
| Annotation | @WebMvcTest | @SpringBootTest |
| Layers Tested | Only the Controller / Web layer | All layers: Controller, Service, Repository, Database |
| Database Access | No (services are mocked) | Yes (real database or test container) |
| Speed | Fast (lightweight, focused tests) | Slower (loads full application context) |
| Purpose | Ensures API endpoints work correctly | Tests end-to-end application flow, including DB and services |
| Use Case | Unit-style controller tests, HTTP requests, validation, headers, JSON responses | Full integration tests, complex workflows, real database interactions, microservice communication |
Controller testing in Spring Boot ensures that your REST APIs are correct, secure, and stable. By using:
@WebMvcTestMockMvc@MockBeanyou can confidently test request mappings, HTTP methods, headers, validation, and responses—without loading the full application