skip to content

Instead of @SpringBootTest, which slice would you pick for a controller vs a repository, and what does each load?

level: middleimportance: must knowfreq 68%

answer

  1. @WebMvcTest = MVC only + MockMvc + @MockBean services
  2. @DataJpaTest = JPA + embedded DB + rollback
  3. slices skip unrelated beans/auto-config
  4. same slice config => shared cached context
  5. Replace.NONE for real DB

basics

~10 s

Use @WebMvcTest for a controller — it loads only the web/MVC layer and mocks the rest. Use @DataJpaTest for a repository — it loads JPA/Hibernate plus an in-memory (or configured) database, nothing else.

solid answer

~40 s

Slice annotations build a *minimal* context for one layer. For a controller I use `@WebMvcTest(FooController.class)`: it auto-configures Spring MVC (`MockMvc`), Jackson, converters, filters, and controller-advice, but does **not** create services or repositories — I supply those with `@MockBean`. For a repository I use `@DataJpaTest`: it configures the `EntityManager`, Hibernate, Spring Data repositories, and a transactional, rolled-back test with an embedded DB (or the real one via `@AutoConfigureTestDatabase(replace=NONE)`). Other slices: `@JsonTest` (Jackson serialization), `@RestClientTest` (RestTemplate/WebClient), `@WebFluxTest` (reactive controllers), `@DataMongoTest`, etc. Slices are dramatically faster than `@SpringBootTest` because they skip unrelated beans and auto-config, and — importantly — several tests sharing the same slice configuration share one cached context.

code

java · 29 lines
java
// Controller slice: only MVC layer; service is mocked.
@WebMvcTest(OrderController.class)
class OrderControllerTest {

    @Autowired MockMvc mvc;
    @MockBean OrderService orderService; // NOT loaded by the slice — must mock

    @Test
    void returnsOrder() throws Exception {
        given(orderService.find(1L)).willReturn(new Order(1L));
        mvc.perform(get("/orders/1"))
           .andExpect(status().isOk())
           .andExpect(jsonPath("$.id").value(1));
    }
}

// Repository slice: JPA + embedded DB, transactional rollback per test.
@DataJpaTest
class OrderRepositoryTest {

    @Autowired OrderRepository repo;
    @Autowired TestEntityManager em;

    @Test
    void findsByStatus() {
        em.persist(new Order(OrderStatus.NEW));
        assertThat(repo.findByStatus(OrderStatus.NEW)).hasSize(1);
    }
}

go deeper

for a junior

Knows the two main slices exist and roughly what each is for.

for a middle

Can name what each slice loads/omits and wire @MockBean / TestEntityManager correctly.

for a senior

Chooses the narrowest correct slice, handles Replace.NONE and security-in-WebMvcTest gotchas.

for a principal

Defines team conventions: slices by default, @SpringBootTest reserved for wiring/e2e, and standard configs to maximize cache reuse.

## Slice tests Spring Boot ships **test slices** — annotations that assemble a *narrow* `ApplicationContext` containing only the beans relevant to one layer. Each is composed of `@...Test` + `@AutoConfigure...` meta-annotations. They exist precisely to avoid the full-context cost of `@SpringBootTest`. ### @WebMvcTest — the web/MVC layer - Auto-configures **Spring MVC** infrastructure: `MockMvc`, `@Controller`/`@RestController` beans, `@ControllerAdvice`, `HttpMessageConverter`s (Jackson), `Filter`s, `WebMvcConfigurer`s, validation. - Does **NOT** load `@Service`, `@Repository`, `@Component` (general), or the persistence/auto-config for a `DataSource`. - You inject collaborators the controller needs with **`@MockBean`** (creates a Mockito mock and puts it in the context). - Narrow it to one controller: `@WebMvcTest(FooController.class)` — otherwise it registers *all* controllers. - Drive it with the injected `MockMvc` (no real server; requests go through the MVC dispatcher in-memory). - Security note: Spring Security auto-config IS applied in `@WebMvcTest`, so endpoints may return 401/403 unless you configure it or use `spring-security-test`. ### @DataJpaTest — the JPA persistence layer - Auto-configures **JPA**: `EntityManager`/`EntityManagerFactory`, Hibernate, Spring Data JPA repositories, a `DataSource`, and `TestEntityManager`. - By default **replaces** your DataSource with an **embedded in-memory DB** (H2/HSQL/Derby) — controlled by `@AutoConfigureTestDatabase`. Use `@AutoConfigureTestDatabase(replace = Replace.NONE)` to test against the real configured DB (e.g., with Testcontainers). - Each test runs in a **transaction that is rolled back** at the end, so tests don't pollute each other. - Does **NOT** load web beans, services, or general components. ### Other common slices - `@JsonTest` — Jackson/Gson (de)serialization, `JacksonTester`. - `@RestClientTest` — `RestTemplate`/`RestClient`/`WebClient` with `MockRestServiceServer`. - `@WebFluxTest` — reactive controllers with `WebTestClient`. - `@DataMongoTest`, `@DataRedisTest`, `@JdbcTest`, `@DataR2dbcTest`, etc. ## Why slices are fast - They register a **fraction** of the beans and skip most auto-configurations. - Fewer, well-defined configurations mean the **context cache** is highly effective: every `@DataJpaTest` (with the same settings) shares one context; every `@WebMvcTest` with identical config shares another. ## Choosing | Need | Use | |---|---| | Test HTTP mapping, status, JSON, validation of a controller | `@WebMvcTest` + `@MockBean` service | | Test a query method / entity mapping | `@DataJpaTest` | | Test full request → DB round trip / wiring | `@SpringBootTest` (often `RANDOM_PORT`) | | Pure serialization | `@JsonTest` | ## Gotchas - `@WebMvcTest` **won't** find your service beans — forgetting `@MockBean` yields a `NoSuchBeanDefinitionException`. - `@DataJpaTest` silently swaps to H2 unless you disable replacement; H2 dialect differences can hide real-DB bugs. - Adding `@SpringBootTest` behavior into a slice (e.g., `@Import` of many configs, or `@MockBean` combinations) fragments the cache. - If your controller depends on security or custom converters, you may need extra `@Import`/`@AutoConfigure...`.

  • In a @WebMvcTest, why do you get NoSuchBeanDefinitionException for your service?
    Because the web slice only loads MVC/controller beans, not @Service beans. You must provide the collaborator with @MockBean (or @Import a config that defines it).
  • Does @DataJpaTest use your production database?
    By default no — it replaces the DataSource with an embedded in-memory DB. Set @AutoConfigureTestDatabase(replace = Replace.NONE) to use the real configured datasource (e.g., Testcontainers).

saying these in an interview costs you the question

  • Claiming @WebMvcTest loads services and repositories (it doesn't).
  • Thinking @DataJpaTest hits the production DB by default (it swaps in an embedded DB).
  • Using @SpringBootTest for a plain controller-mapping test when @WebMvcTest suffices.

context