What is the difference between @SpringBootTest and the "slice" test annotations like @WebMvcTest and @DataJpaTest?
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 theEntityManager, without the web layer at all — great for testing repository query behavior in isolation.@JsonTest— auto-configures just Jackson'sObjectMapperand 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.