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) — 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 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 — and reserve @SpringBootTest for genuinely full end-to-end integration tests where the interaction between multiple layers is specifically what's being verified.

Related Resources