skip to content

What is a Spring Boot test slice, and how does a slice like @WebMvcTest differ from @SpringBootTest?

level: juniorimportance: must knowfreq 78%

answer

  1. Slice = one layer only
  2. @WebMvcTest web, @DataJpaTest repos, @JsonTest jackson
  3. no @Service/@Repository in @WebMvcTest — mock them
  4. @SpringBootTest = whole context
  5. faster + focused failures

basics

~20 s

A test slice loads only the part of the application relevant to one layer (e.g. web MVC) instead of the whole app. @SpringBootTest starts the full context; @WebMvcTest loads only web components, so tests are faster and focused.

solid answer

~40 s

A slice is a focused test annotation (like @WebMvcTest, @DataJpaTest, @JsonTest) that boots a minimal Spring context containing only the beans and auto-configuration needed for one layer. @SpringBootTest, by contrast, loads the entire application context with all auto-configuration active. With @WebMvcTest you get the MVC infrastructure (controllers, converters, MockMvc) but not @Service or @Repository beans — you mock collaborators with @MockBean/@MockitoBean. Slices are much faster because far fewer beans are created, and they isolate failures to one layer. The trade-off is you must explicitly add anything outside the slice's scope. Use slices for targeted layer tests; use @SpringBootTest for end-to-end or wiring-sensitive integration tests.

code

java · 19 lines
java
@WebMvcTest(GreetingController.class)
class GreetingControllerTest {

    @Autowired
    MockMvc mvc;

    // GreetingService lives in the service layer, which the slice does NOT load
    @MockitoBean
    GreetingService greetingService;

    @Test
    void returnsGreeting() throws Exception {
        given(greetingService.greet("Ann")).willReturn("Hi Ann");

        mvc.perform(get("/greet/Ann"))
           .andExpect(status().isOk())
           .andExpect(content().string("Hi Ann"));
    }
}

go deeper

for a junior

Know that a slice loads only one layer and is faster than @SpringBootTest; name @WebMvcTest / @DataJpaTest / @JsonTest.

for a middle

Explain the component-scan filtering and that collaborators must be mocked; know MockMvc is provided, no real server.

for a senior

Contrast context caching, when to reach for @SpringBootTest, and the transactional/embedded-DB behavior of @DataJpaTest.

for a principal

Discuss the cost of many distinct slice contexts on suite time and how to standardize slice usage across teams.

## What a test slice is Spring Boot **test slices** are specialized test annotations that start a *cut-down* application context containing only the beans relevant to one 'slice' (layer) of the application. Examples: `@WebMvcTest` (Spring MVC web layer), `@DataJpaTest` (JPA repositories + embedded DB), `@JsonTest` (Jackson/Gson serialization), `@RestClientTest`, `@WebFluxTest`, `@JdbcTest`, `@DataMongoTest`, and more. ## Why slices exist `@SpringBootTest` loads the **whole** `ApplicationContext`: every `@Component`, `@Service`, `@Repository`, `@Controller`, plus *all* matching auto-configuration. That is powerful but slow and broad — a failure anywhere breaks the test. A slice instead: 1. **Restricts component scanning** — only certain stereotype annotations are picked up. `@WebMvcTest` includes `@Controller`, `@ControllerAdvice`, `@JsonComponent`, `Converter`, `Filter`, `WebMvcConfigurer`, `HandlerMethodArgumentResolver` — but **not** `@Component`, `@Service`, `@Repository`. 2. **Enables only relevant auto-configuration** — instead of every auto-config class, only the ones for that layer are applied (e.g. `WebMvcAutoConfiguration`, `JacksonAutoConfiguration` for `@WebMvcTest`). The result: a context with maybe a dozen beans instead of hundreds. Tests start in a fraction of the time and pinpoint failures to the layer under test. ## How you use one With `@WebMvcTest(GreetingController.class)` you get a configured `MockMvc` bean auto-wired in, and you provide the controller's collaborators as mocks: ```java @WebMvcTest(GreetingController.class) class GreetingControllerTest { @Autowired MockMvc mvc; @MockitoBean GreetingService service; // service layer not loaded — supply a mock } ``` (`@MockBean` in older Boot; `@MockitoBean` from Spring Framework 6.2 / Boot 3.4.) ## Contrast with @SpringBootTest | | `@WebMvcTest` (slice) | `@SpringBootTest` | |---|---|---| | Context | minimal, web-only | full application | | Beans | web stereotypes only | everything | | Auto-config | web subset | all | | Speed | fast | slower | | Server | mocked (MockMvc) | none by default; real port with `webEnvironment` | ## When to use which - **Slice** — testing one layer in isolation (a controller's request mapping/validation, a repository's queries, JSON mapping). Mock everything outside the slice. - **@SpringBootTest** — verifying that layers wire together, security filter chains, or full request→DB flows. ## Gotchas - A slice will **not** find your `@Service` beans — that's by design; mock them or you'll get an unsatisfied-dependency error. - Slices apply their own filtering, so a broad `@Component` you rely on won't be present. - Each distinct slice configuration is a separate context; the test framework caches them, but many different slice setups still cost startup time.

  • Why doesn't @WebMvcTest pick up your @Service beans?
    The slice's component-scan filter deliberately excludes non-web stereotypes (@Component/@Service/@Repository). Only web-layer beans are scanned, so you must supply collaborators as mocks (@MockitoBean/@MockBean).
  • How does @DataJpaTest handle the database?
    By default it replaces the configured DataSource with an in-memory embedded DB (H2/HSQL/Derby) and wraps each test in a rolled-back transaction. Use @AutoConfigureTestDatabase(replace = NONE) to test against the real DB.

saying these in an interview costs you the question

  • Thinking @WebMvcTest loads the whole context like @SpringBootTest
  • Expecting @Service/@Repository beans to be available inside a web slice
  • Believing slices start an embedded servlet server (they use MockMvc, no real port)

context