Bird
Raised Fist0
JUnittesting~15 mins

@WebMvcTest for controller testing in JUnit - Deep Dive

Choose your learning style10 modes available
Overview - Webmvctest For Controller Testing
What is it?
WebMvcTest is a testing annotation in Spring Boot that helps test only the web layer of an application, focusing on controllers. It loads a minimal Spring context containing the controller and related components like filters and advice, but not the full application. This allows fast and focused tests on HTTP requests and responses without starting the entire server. It is commonly used with JUnit to write automated tests for REST APIs or web controllers.
Why it matters
Without WebMvcTest, testing controllers often requires loading the full application context, which is slow and complex. This slows down development and makes it harder to isolate controller logic from other layers like services or databases. WebMvcTest solves this by loading only what is needed for web layer testing, making tests faster, more reliable, and easier to write. This improves developer productivity and confidence in web endpoints.
Where it fits
Before learning WebMvcTest, you should understand basic Spring Boot applications, controllers, and JUnit testing. After mastering WebMvcTest, you can explore full integration testing with @SpringBootTest, mocking service layers, and testing security or filters in the web layer.
Mental Model
Core Idea
WebMvcTest isolates and tests only the web controller layer by loading a minimal Spring context focused on HTTP request handling.
Think of it like...
Testing a controller with WebMvcTest is like testing a car's steering wheel separately without starting the whole engine or driving the car. You focus only on the part that controls direction.
┌─────────────────────────────┐
│ Full Spring Boot Application │
│ ┌─────────────┐             │
│ │ Controller  │             │
│ ├─────────────┤             │
│ │ Service     │             │
│ │ Repository  │             │
│ └─────────────┘             │
└─────────────────────────────┘

WebMvcTest loads only:

┌─────────────┐
│ Controller  │
│ + Web Layer │
└─────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Controller Role
🤔
Concept: Learn what a controller does in a Spring Boot app and why it needs testing.
A controller handles HTTP requests and returns responses. It acts like a traffic cop directing requests to the right place. Testing controllers ensures that when a user sends a request, the app responds correctly.
Result
You know the controller is the web layer entry point and why testing it matters.
Understanding the controller's role helps focus testing on the right layer and avoid unnecessary complexity.
2
FoundationBasics of JUnit Testing
🤔
Concept: Learn how to write simple tests using JUnit framework.
JUnit lets you write methods annotated with @Test that run automatically to check code behavior. Assertions verify expected outcomes. For example, assertEquals checks if two values match.
Result
You can write and run basic tests to verify code correctness.
Knowing JUnit basics is essential because WebMvcTest builds on this framework for controller tests.
3
IntermediateIntroducing @WebMvcTest Annotation
🤔Before reading on: do you think @WebMvcTest loads the full application context or only the web layer? Commit to your answer.
Concept: @WebMvcTest loads only the web layer components needed to test controllers, not the full app.
Annotate your test class with @WebMvcTest(YourController.class) to load only that controller and related web components. This speeds up tests and isolates controller logic.
Result
Tests run faster and focus only on controller behavior without unrelated beans.
Understanding that @WebMvcTest limits context loading prevents slow tests and helps isolate bugs in the web layer.
4
IntermediateUsing MockMvc for HTTP Testing
🤔Before reading on: do you think MockMvc sends real HTTP requests or simulates them in tests? Commit to your answer.
Concept: MockMvc simulates HTTP requests and responses without starting a server.
Inject MockMvc in your test and use it to perform HTTP methods like GET or POST. You can check status codes, response content, and headers with fluent assertions.
Result
You can test controller endpoints as if sending real HTTP requests, but faster and without network overhead.
Knowing MockMvc simulates requests helps write fast, reliable tests that verify controller behavior end-to-end.
5
IntermediateMocking Service Layer Dependencies
🤔Before reading on: do you think @WebMvcTest loads service beans automatically? Commit to your answer.
Concept: @WebMvcTest does not load service or repository beans, so you must mock them.
Use @MockBean to create mock instances of services your controller depends on. Define their behavior with Mockito to isolate controller tests from business logic.
Result
Controller tests focus only on web logic, avoiding failures from service layer bugs.
Understanding mocking prevents test failures caused by missing or complex service dependencies.
6
AdvancedTesting Exception Handling and Advice
🤔Before reading on: do you think @WebMvcTest includes controller advice and exception handlers by default? Commit to your answer.
Concept: @WebMvcTest loads controller advice and exception handlers to test error responses.
You can verify that your controller returns correct HTTP status and messages when exceptions occur by testing with MockMvc. This ensures your API handles errors gracefully.
Result
Tests confirm that error handling works as expected, improving API robustness.
Knowing that advice is included helps write comprehensive tests covering both success and failure cases.
7
ExpertLimitations and Pitfalls of WebMvcTest
🤔Before reading on: do you think WebMvcTest can test security filters and full integration scenarios? Commit to your answer.
Concept: WebMvcTest is limited to web layer and does not load full security or database layers.
For testing security filters or database integration, use @SpringBootTest or specialized test slices. WebMvcTest is not suitable for full end-to-end tests.
Result
You avoid misusing WebMvcTest and choose the right test type for your needs.
Understanding WebMvcTest limits prevents false confidence from incomplete tests and guides proper test strategy.
Under the Hood
WebMvcTest uses Spring's testing support to create a minimal ApplicationContext containing only beans related to the web layer, such as controllers, Jackson converters, and validation. It excludes service, repository, and other beans unless explicitly mocked. MockMvc is configured to simulate HTTP requests by invoking controller methods directly without starting a real server. This lightweight context speeds up tests and isolates controller logic.
Why designed this way?
Spring Boot developers wanted fast, focused tests for controllers without the overhead of loading the entire application. Full context loading is slow and can hide bugs due to unrelated beans. By slicing the context to only web components, WebMvcTest balances test speed and coverage. Alternatives like full integration tests exist but are slower and less focused.
┌───────────────────────────────┐
│ Spring Test Framework          │
│ ┌───────────────────────────┐ │
│ │ WebMvcTest Annotation      │ │
│ │ - Loads Controller Beans   │ │
│ │ - Loads Web Configurations │ │
│ │ - Excludes Services/Repos  │ │
│ └─────────────┬─────────────┘ │
│               │               │
│        ┌──────▼───────┐       │
│        │ MockMvc      │       │
│        │ - Simulates  │       │
│        │   HTTP Calls │       │
│        └──────────────┘       │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does @WebMvcTest load service and repository beans by default? Commit to yes or no.
Common Belief:Yes, @WebMvcTest loads all beans including services and repositories automatically.
Tap to reveal reality
Reality:No, @WebMvcTest loads only web layer beans like controllers. Services and repositories must be mocked explicitly.
Why it matters:Assuming services are loaded causes NullPointerExceptions or test failures due to missing beans.
Quick: Does MockMvc send real HTTP requests over the network? Commit to yes or no.
Common Belief:MockMvc sends real HTTP requests to a running server during tests.
Tap to reveal reality
Reality:MockMvc simulates HTTP requests internally without network calls or starting a server.
Why it matters:Thinking MockMvc uses real network slows down tests and misleads debugging efforts.
Quick: Can WebMvcTest fully test security filters and database integration? Commit to yes or no.
Common Belief:Yes, WebMvcTest covers security filters and database layers fully.
Tap to reveal reality
Reality:No, WebMvcTest excludes security filters and database layers; full integration tests are needed for those.
Why it matters:Relying on WebMvcTest alone misses critical security and data integration bugs.
Quick: Does @WebMvcTest automatically include controller advice for exception handling? Commit to yes or no.
Common Belief:No, controller advice must be manually included in WebMvcTest.
Tap to reveal reality
Reality:Yes, WebMvcTest loads controller advice and exception handlers by default.
Why it matters:Not testing advice leads to missing verification of error responses and API robustness.
Expert Zone
1
MockMvc can be customized with filters and interceptors to simulate complex web scenarios, but these must be explicitly configured.
2
When multiple controllers exist, specifying which controller to test with @WebMvcTest limits context size and speeds tests.
3
Combining @WebMvcTest with @Import or @ContextConfiguration allows injecting additional beans selectively for more complex tests.
When NOT to use
Do not use WebMvcTest when you need to test full application behavior including security filters, database access, or asynchronous processing. Instead, use @SpringBootTest with a real server or specialized test slices like @DataJpaTest for repositories.
Production Patterns
In real projects, WebMvcTest is used for fast feedback on controller logic during development. It is combined with Mockito for mocking services and with integration tests for full system validation. Teams often write WebMvcTest tests for each REST endpoint to ensure API contracts remain stable.
Connections
Mocking with Mockito
Builds-on
Understanding Mockito helps isolate controller tests by mocking dependencies, making WebMvcTest more effective.
Integration Testing with @SpringBootTest
Complementary
Knowing the difference between WebMvcTest and @SpringBootTest guides choosing the right test scope for speed versus coverage.
Network Protocol Testing
Similar pattern
Simulating HTTP requests in WebMvcTest is like testing network protocols with mock packets, focusing on message handling without real transmission.
Common Pitfalls
#1Forgetting to mock service dependencies causes test failures.
Wrong approach:@WebMvcTest(MyController.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @Test void testEndpoint() throws Exception { mockMvc.perform(get("/api/data")) .andExpect(status().isOk()); } }
Correct approach:@WebMvcTest(MyController.class) class MyControllerTest { @Autowired private MockMvc mockMvc; @MockBean private MyService myService; @Test void testEndpoint() throws Exception { when(myService.getData()).thenReturn("mocked data"); mockMvc.perform(get("/api/data")) .andExpect(status().isOk()) .andExpect(content().string("mocked data")); } }
Root cause:Misunderstanding that @WebMvcTest does not load service beans automatically.
#2Trying to test security filters with WebMvcTest alone.
Wrong approach:@WebMvcTest(SecureController.class) class SecureControllerTest { @Autowired private MockMvc mockMvc; @Test void testSecureEndpoint() throws Exception { mockMvc.perform(get("/secure")) .andExpect(status().isUnauthorized()); } }
Correct approach:@SpringBootTest @AutoConfigureMockMvc class SecureControllerIntegrationTest { @Autowired private MockMvc mockMvc; @Test void testSecureEndpoint() throws Exception { mockMvc.perform(get("/secure")) .andExpect(status().isUnauthorized()); } }
Root cause:Assuming WebMvcTest loads security filters and full context.
#3Expecting MockMvc to perform real network calls.
Wrong approach:mockMvc.perform(get("http://localhost:8080/api")) .andExpect(status().isOk());
Correct approach:mockMvc.perform(get("/api")) .andExpect(status().isOk());
Root cause:Misunderstanding that MockMvc simulates requests internally without network.
Key Takeaways
WebMvcTest is a focused Spring Boot test annotation that loads only the web layer, enabling fast and isolated controller tests.
MockMvc simulates HTTP requests and responses without starting a real server, making web tests efficient and reliable.
Service and repository beans are not loaded by WebMvcTest and must be mocked to isolate controller logic.
WebMvcTest includes controller advice and exception handlers, allowing testing of error responses.
For full integration tests including security and database, use @SpringBootTest instead of WebMvcTest.

Practice

(1/5)
1. What is the main purpose of using @WebMvcTest in Spring Boot testing?
easy
A. To test only the Spring MVC controllers without starting the full application context
B. To test the entire application including database and services
C. To perform integration testing of all layers
D. To mock external APIs automatically

Solution

  1. Step 1: Understand the role of @WebMvcTest

    @WebMvcTest is designed to load only the Spring MVC components, mainly controllers, for focused testing.
  2. Step 2: Compare with other test types

    Unlike full integration tests, it does not load services or repositories, making tests faster and isolated.
  3. Final Answer:

    To test only the Spring MVC controllers without starting the full application context -> Option A
  4. Quick Check:

    @WebMvcTest = Controller-only test [OK]
Hint: Remember: @WebMvcTest loads controllers only, not full app [OK]
Common Mistakes:
  • Thinking @WebMvcTest loads full application context
  • Confusing @WebMvcTest with @SpringBootTest
  • Assuming it mocks external APIs automatically
2. Which annotation is used to mock a service dependency inside a @WebMvcTest annotated test class?
easy
A. @InjectMocks
B. @MockMvc
C. @Autowired
D. @MockBean

Solution

  1. Step 1: Identify mocking annotation for Spring beans

    @MockBean is used to add mock implementations of Spring beans into the application context during tests.
  2. Step 2: Differentiate from other annotations

    @MockMvc is not an annotation, @Autowired injects real beans, and @InjectMocks is from Mockito but not for Spring context injection.
  3. Final Answer:

    @MockBean -> Option D
  4. Quick Check:

    Mock dependencies in @WebMvcTest = @MockBean [OK]
Hint: Use @MockBean to mock Spring beans in @WebMvcTest [OK]
Common Mistakes:
  • Using @Autowired instead of @MockBean for mocks
  • Confusing @MockBean with Mockito's @InjectMocks
  • Thinking @MockMvc is an annotation
3. Given the following test snippet using @WebMvcTest and MockMvc:
@WebMvcTest(MyController.class)
class MyControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @Test
  void testHello() throws Exception {
    mockMvc.perform(get("/hello"))
      .andExpect(status().isOk())
      .andExpect(content().string("Hello World"));
  }
}
What will happen if the controller method mapped to /hello returns "Hello World" as response?
medium
A. The test will fail because MockMvc is not autowired correctly
B. The test will pass because the response matches the expected string
C. The test will fail due to status code mismatch
D. The test will throw a NullPointerException

Solution

  1. Step 1: Analyze the test expectations

    The test expects HTTP status 200 OK and response body "Hello World".
  2. Step 2: Match with controller behavior

    If the controller returns "Hello World" with status 200, both expectations are met, so the test passes.
  3. Final Answer:

    The test will pass because the response matches the expected string -> Option B
  4. Quick Check:

    Matching response and status = test pass [OK]
Hint: Match expected status and content to pass MockMvc tests [OK]
Common Mistakes:
  • Assuming test fails if no explicit status set in controller
  • Confusing autowiring issues with test failures
  • Ignoring response content in assertions
4. Consider this test class snippet:
@WebMvcTest(MyController.class)
class MyControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private MyService myService;

  @Test
  void testEndpoint() throws Exception {
    when(myService.getData()).thenReturn("data");
    mockMvc.perform(get("/data"))
      .andExpect(status().isOk())
      .andExpect(content().string("data"));
  }
}
If the test fails with a 404 Not Found error, what is the most likely cause?
medium
A. The test class is missing @SpringBootTest annotation
B. The mock service is not returning the expected value
C. The controller method for /data is missing or not mapped correctly
D. MockMvc is not autowired properly

Solution

  1. Step 1: Understand 404 error in MockMvc test

    A 404 means the requested URL is not found in the controller mappings.
  2. Step 2: Check test setup

    @WebMvcTest loads only controllers; if /data mapping is missing or incorrect, 404 occurs despite mocks.
  3. Final Answer:

    The controller method for /data is missing or not mapped correctly -> Option C
  4. Quick Check:

    404 error = missing controller mapping [OK]
Hint: 404 in @WebMvcTest usually means missing controller mapping [OK]
Common Mistakes:
  • Blaming mock service return value for 404
  • Assuming @SpringBootTest is needed for controller tests
  • Ignoring URL mapping correctness
5. You want to test a controller method that depends on a service returning a list of users. Using @WebMvcTest, how should you mock the service and verify the controller returns JSON with the user list correctly?
hard
A. Use @MockBean to mock the service, stub the method to return a list, then use MockMvc to perform GET and expect JSON content
B. Use @Autowired to inject the real service and call the controller method directly
C. Use @SpringBootTest to load full context and test the controller with real service
D. Use Mockito's @InjectMocks on the controller and call methods without MockMvc

Solution

  1. Step 1: Mock the service dependency with @MockBean

    In @WebMvcTest, use @MockBean to replace the service bean with a mock and stub its method to return the user list.
  2. Step 2: Use MockMvc to perform HTTP GET and verify JSON response

    Perform a GET request on the controller endpoint and assert the JSON response matches the expected user list.
  3. Final Answer:

    Use @MockBean to mock the service, stub the method to return a list, then use MockMvc to perform GET and expect JSON content -> Option A
  4. Quick Check:

    Mock service + MockMvc GET + JSON assert = correct test [OK]
Hint: Mock service with @MockBean and verify JSON via MockMvc [OK]
Common Mistakes:
  • Injecting real service instead of mocking
  • Using full context test instead of @WebMvcTest
  • Calling controller methods directly without MockMvc
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard