What is the difference between @SpringBootTest and the "slice" test annotations like @WebMvcTest and @DataJpaTest?

9 minintermediatespringboottestwebmvctestdatajpatest

Quick Answer

@SpringBootTest boots the entire ApplicationContext (or a meaningfully large slice of it), giving the most realistic end-to-end test, but at a real cost in startup time and broader scope than most individual tests actually need. The "slice" annotations (@WebMvcTest, @DataJpaTest, @JsonTest, etc.) load only the specific subset of auto-configuration relevant to one architectural layer, auto-configuring just what's needed (e.g., @WebMvcTest wires up Spring MVC infrastructure and MockMvc, but not the full persistence layer). They're much faster and more focused, at the cost of not exercising the full stack together.

Detailed Answer

Spring Boot's testing support offers a spectrum from "test everything, realistically" to "test just this one layer, fast":

@SpringBootTest boots the full ApplicationContext (or close to it) — every bean, every auto-configuration, exactly as the real application would start:

@SpringBootTest
class OrderServiceIntegrationTest {
    @Autowired OrderService orderService;
    @Autowired OrderRepository orderRepository;

    @Test
    void createsAndPersistsAnOrder() {
        Order order = orderService.createOrder(new CreateOrderRequest(...));
        assertThat(orderRepository.findById(order.getId())).isPresent();
    }
}

This gives the most realistic test — closest to how the application actually behaves in production. But it comes at a real cost: booting the entire context is comparatively slow, and a test only checking, say, controller-to-service wiring doesn't need the entire persistence layer, security configuration, and every other bean loaded just to verify that.

"Slice" test annotations load only the auto-configuration relevant to one specific architectural layer, leaving everything else out:

  • @WebMvcTest(OrderController.class) — auto-configures Spring MVC infrastructure (MockMvc, message converters, validation) and scans just the specified controller(s), without starting a real embedded server or wiring up the persistence layer, security beans, etc.
@WebMvcTest(OrderController.class)
class OrderControllerTest {
    @Autowired MockMvc mockMvc;
    @MockitoBean OrderService orderService; // service layer replaced with a mock — not a real bean

    @Test
    void returns404WhenOrderNotFound() throws Exception {
        when(orderService.getOrder(99L)).thenThrow(new OrderNotFoundException(99L));
        mockMvc.perform(get("/orders/99")).andExpect(status().isNotFound());
    }
}
  • @DataJpaTest — auto-configures an in-memory (or Testcontainers-backed) database, Spring Data repositories, and the EntityManager, without the web layer at all. Great for testing repository query behavior in isolation.
  • @JsonTest — auto-configures just Jackson's ObjectMapper and related JSON serialization infrastructure, for testing custom serializers/deserializers without any web or persistence concerns.

Practical guidance: reach for the narrowest slice annotation that actually exercises what a given test cares about. It runs faster and fails with a clearer, more targeted signal when something's wrong. Reserve @SpringBootTest for genuinely full end-to-end integration tests where the interaction between multiple layers is specifically what's being verified.

Related Resources