Chapter 9.5☕ 14 min read

Testing REST APIs with MockMvc

You need to test your REST API endpoints to make sure they return the right HTTP status codes and JSON. But starting a real Tomcat server for every test is slow. <strong>MockMvc</strong> allows you to test the web layer without starting a real server.

01The Concept: Simulating HTTP Requests

The Flight Simulator Analogy:

When training pilots in Hyderabad, they don't put a student in a real ₹100 crore Airbus on the first day. They put them in a flight simulator. The simulator mimics the controls, the weather, and the dashboard perfectly, but the plane never leaves the ground.

MockMvc is a flight simulator for your Spring Boot app. It fakes HTTP requests (GET, POST) and sends them to your controllers. The controller runs, but Tomcat never actually starts. This makes your web tests incredibly fast.

02Technical Explanation
  1. @WebMvcTest: A specialized test annotation that boots only the web layer (Controllers, JSON converters). It does NOT boot your Services or Repositories.
  2. @MockBean: Because @WebMvcTest doesn't boot the Service layer, you must create a fake (mock) Service bean for the Controller to talk to.
  3. MockMvc: The object used to build and execute fake HTTP requests and assert the responses.
  4. @AutoConfigureMockMvc: Automatically configures the MockMvc instance.
03Full Working Code: Testing a Controller
package com.devinhyderabad;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

// 1. Boot only the BookController (Web Layer)
@WebMvcTest(BookController.class)
public class BookControllerTest {

@Autowired
private MockMvc mockMvc; // The flight simulator

// 2. Fake the Service layer (since @WebMvcTest doesn't load it)
@MockBean
private BookService bookService;

@Test
public void testGetBookById_ReturnsJsonAnd200() throws Exception {

// 3. Arrange: Train the mock service
Book mockBook = new Book(1L, "MockMvc Guide", "Deva");
when(bookService.getBookById(1L)).thenReturn(mockBook);

// 4. Act & Assert: Perform a fake GET request and check the response
mockMvc.perform(get("/api/books/1"))
.andExpect(status().isOk()) // Expect HTTP 200
.andExpect(jsonPath("$.title").value("MockMvc Guide")); // Expect JSON field
}
}
04Why It Matters

Interview Question: "What is the difference between @SpringBootTest and @WebMvcTest?"

Answer: @SpringBootTest loads the entire application context (Controllers, Services, Repositories, DB). It is slow but tests everything. @WebMvcTest loads only the web layer (the specified Controller). It does not load the database or services. It is extremely fast and is used specifically for testing HTTP request/response mapping, status codes, and JSON serialization.

05Interview Note

Enterprise Note: MockMvc is perfect for testing 400 Bad Request validation errors. You can send a faulty JSON payload to your endpoint and assert that Spring returns a 400 status, ensuring your @Valid annotations are working correctly without needing a database.

Key Takeaways

  • ✅ @WebMvcTest boots only the web layer (Controllers) — no full Spring context
  • ✅ @MockBean is used to fake the Service layer in @WebMvcTest
  • ✅ MockMvc performs fake HTTP requests and asserts responses without starting Tomcat
  • ✅ MockMvc is ideal for testing @Valid validation errors (400 Bad Request)