How do @TestConfiguration and test doubles behave inside slice tests like @WebMvcTest or @DataJpaTest, compared to a full @SpringBootTest?
answer
- slice = trimmed context, one layer
- @WebMvcTest excludes services => @MockBean them
- nested @TestConfiguration applies; top-level needs @Import
- @DataJpaTest: embedded DB + rollback per test
- slices disable full component scan
basics
~20 sSlice tests load only a narrow part of the context. A nested static @TestConfiguration in the test still applies, but auto-detection of other @TestConfiguration classes is limited, so you usually add fixtures with @Import. Collaborators outside the slice must be supplied as @MockBean or fake @Beans.
solid answer
~40 sSlice annotations (`@WebMvcTest`, `@DataJpaTest`, `@JsonTest`, etc.) load only a **focused subset** of the context — for `@WebMvcTest`, the web layer (controllers, `MockMvc`, converters) but **not** your services or repositories. So beans a controller depends on must be provided: idiomatically via `@MockBean`, or as fake `@Bean`s. A **nested static `@TestConfiguration`** in the slice test is still applied. However, slice tests **disable full component scanning**, so top-level `@TestConfiguration` classes are pulled in with `@Import`, and user configuration isn't auto-loaded the way it is in `@SpringBootTest`. `@DataJpaTest` similarly loads JPA/repository infrastructure plus an embedded DB but not your `@Service` beans. The pattern: keep the slice narrow, supply just the collaborators the slice needs as mocks or fakes.
code
java · 21 lines@WebMvcTest(OrderController.class) // loads ONLY the web layer
class OrderControllerTest {
@Autowired MockMvc mockMvc;
@MockBean OrderService orderService; // service isn't in the slice -> must supply it
// Slice-local fixture still works when nested + static
@TestConfiguration
static class WebFixtures {
@Bean
ClockHolder clockHolder() { return new ClockHolder(Clock.systemUTC()); }
}
@Test
void returns404ForMissingOrder() throws Exception {
when(orderService.find("x")).thenReturn(Optional.empty());
mockMvc.perform(get("/orders/x"))
.andExpect(status().isNotFound());
}
}go deeper
Know slices load one layer and you mock the rest with @MockBean.
Explain nested vs. top-level @TestConfiguration behavior in slices and @DataJpaTest's embedded-DB + rollback defaults.
Discuss cache-key impact of mocks in slices and when a slice's partial auto-config forces extra @Import/@AutoConfigure.
Define a layering test strategy: slices for fast per-layer coverage, targeted full @SpringBootTest for integration, minimizing context proliferation.
## What a slice test is Slice annotations create a **trimmed-down ApplicationContext** containing only the beans relevant to one layer, for speed and focus: - `@WebMvcTest` — Spring MVC infrastructure: your `@Controller`/`@RestController` under test, `MockMvc`, `@ControllerAdvice`, converters, `WebMvcConfigurer`, filters. **Excludes** `@Service`, `@Repository`, `@Component` beans. - `@DataJpaTest` — JPA `@Entity` scanning, Spring Data repositories, `TestEntityManager`, an embedded (or configured) datasource; transactional + rolled back per test. **Excludes** the service layer. - `@JsonTest`, `@RestClientTest`, `@DataMongoTest`, etc. — analogous focused slices. ## How fixtures/doubles apply in slices - **Nested static `@TestConfiguration`**: still detected and applied for that test — this is your primary hook to add slice-local beans. - **Top-level `@TestConfiguration`**: not auto-scanned (slices disable full scan), so use `@Import(...)`. - **Collaborators outside the slice**: must be supplied. In `@WebMvcTest`, the controller's `@Service` dependency isn't loaded, so you provide it with `@MockBean` (idiomatic) or a fake `@Bean`. Omitting it yields a context-startup failure (unsatisfied dependency). ## Why not just use @SpringBootTest everywhere? Slices are **much faster** (smaller context) and enforce layer isolation. But because they exclude collaborators, they lean heavily on test doubles — that's by design. Note `@MockBean` in slices still participates in the **context cache key**, so varied mock sets fragment the cache within the slice too. ## @DataJpaTest specifics - Runs in a transaction that is **rolled back** after each test, keeping the DB clean. - By default uses an **embedded** database, replacing your configured one; override with `@AutoConfigureTestDatabase(replace = NONE)` to hit the real/configured DB. - A nested `@TestConfiguration` can add repository fixtures, custom `AuditorAware`, or seed helpers. ## Common gotchas - Autowiring a `@Service` in a `@WebMvcTest` and forgetting to `@MockBean` it → `UnsatisfiedDependencyException` / no qualifying bean. - Expecting security/filters config to be identical to production — slices apply a subset of auto-config; you may need `@Import` of specific config or `@AutoConfigure...` companions. - Assuming a top-level `@TestConfiguration` loads automatically — it needs `@Import`. - `@DataJpaTest` silently swapping to an embedded DB and masking DB-specific behavior. ## When to use which - Testing controller request/response mapping, validation, status codes → `@WebMvcTest` + `@MockBean` services. - Testing repository queries/mappings → `@DataJpaTest`. - Testing cross-layer behavior end to end → full `@SpringBootTest` with fakes/`@Import` fixtures.
- In a @WebMvcTest, why does autowiring a @Service without @MockBean fail?@WebMvcTest loads only web-layer beans, not @Service components. The controller's dependency has no bean to satisfy it, so context startup fails with an unsatisfied-dependency error. You must supply it via @MockBean or a fake @Bean.
- How do you make @DataJpaTest run against your real configured database instead of an embedded one?Annotate with @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE), which stops Boot from swapping in an embedded datasource, so the configured DataSource is used.
saying these in an interview costs you the question
- Thinking a slice test loads the full application context.
- Expecting @Service/@Repository beans to be available in @WebMvcTest.
- Assuming a top-level @TestConfiguration auto-loads in a slice.
- Not knowing @DataJpaTest defaults to an embedded DB and rolls back per test.