0
0
SpringbootComparisonBeginner · 4 min read

@SpringBootTest vs @WebMvcTest: Key Differences and Usage

@SpringBootTest loads the full Spring application context for integration testing, while @WebMvcTest loads only the web layer for focused controller testing. Use @SpringBootTest for end-to-end tests and @WebMvcTest for fast, slice tests of MVC controllers.
⚖️

Quick Comparison

This table summarizes the main differences between @SpringBootTest and @WebMvcTest.

Aspect@SpringBootTest@WebMvcTest
ScopeLoads full application contextLoads only web layer (controllers, MVC components)
Test TypeIntegration testSlice test (focused unit test)
SpeedSlower due to full contextFaster, lightweight context
Use CaseEnd-to-end flow and service integrationController logic and web layer behavior
Auto-configured BeansAll beans loadedOnly MVC-related beans loaded
MockingUsually real beans, can mock manuallyAuto-configures MockMvc and mocks service beans
⚖️

Key Differences

@SpringBootTest boots up the entire Spring application context, including all beans, configurations, and embedded servers if needed. This makes it suitable for integration tests that verify how different parts of the app work together, such as controllers, services, repositories, and database access.

In contrast, @WebMvcTest slices the application context to load only the web layer components like controllers, filters, and MVC configurations. It excludes service and repository beans unless explicitly mocked. This makes tests faster and focused on web layer behavior, such as request handling, validation, and response formatting.

While @SpringBootTest is heavier and slower, it provides a realistic environment for full-stack testing. @WebMvcTest is lightweight and ideal for unit testing controllers without starting the full application or database.

⚖️

Code Comparison

Example of a test using @SpringBootTest to test a controller with full context.

java
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingControllerSpringBootTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void testGreeting() {
        ResponseEntity<String> response = restTemplate.getForEntity("/greeting", String.class);
        assert(response.getBody().contains("Hello"));
    }
}
Output
Test passes if /greeting endpoint returns a response containing "Hello"
↔️

@WebMvcTest Equivalent

Equivalent test using @WebMvcTest to test the same controller with mocked dependencies.

java
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.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(GreetingController.class)
public class GreetingControllerWebMvcTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private GreetingService greetingService; // Mock service dependency

    @Test
    public void testGreeting() throws Exception {
        // Mock service behavior
        org.mockito.Mockito.when(greetingService.greet()).thenReturn("Hello from mock");

        mockMvc.perform(get("/greeting"))
               .andExpect(status().isOk())
               .andExpect(content().string("Hello from mock"));
    }
}
Output
Test passes if /greeting endpoint returns mocked "Hello from mock" response
🎯

When to Use Which

Choose @SpringBootTest when you want to test the full application behavior including service layers, repositories, and real integrations. It is best for end-to-end integration tests that verify the entire stack works together.

Choose @WebMvcTest when you want fast, focused tests of your web layer, especially controllers, without loading the full context or database. It is ideal for unit testing controller logic and HTTP request/response handling.

Key Takeaways

@SpringBootTest loads the full app context for integration tests.
@WebMvcTest loads only the web layer for fast, focused controller tests.
Use @SpringBootTest for end-to-end flow and real bean interactions.
Use @WebMvcTest for isolated controller logic and HTTP behavior.
Mock dependencies in @WebMvcTest to keep tests lightweight.