skip to content

When and how would you use the classes attribute of @SpringBootTest to override configuration detection?

level: middleimportance: should knowfreq 55%

answer

  1. classes = ... skips the package search
  2. Only listed beans + their imports/scans
  3. Plain @Configuration => no component scan, no auto-config
  4. Use for leaner/faster or library modules
  5. Boot front for @ContextConfiguration(classes)

basics

~10 s

Set @SpringBootTest(classes = {MyConfig.class}) to tell the test exactly which @Configuration classes to load. This bypasses the package-tree search entirely, so the context contains only what those classes define plus what they import.

solid answer

~40 s

The `classes` attribute lets you name the configuration classes explicitly instead of relying on `@SpringBootConfiguration` discovery. Passing `@SpringBootTest(classes = TestConfig.class)` short-circuits the upward package search — the finder is never consulted. Use it when: the auto-discovered main class pulls in too much (heavy auto-configuration, external clients) and you want a leaner, faster context; when there's no `@SpringBootApplication` reachable from the test (e.g. a library module); or when two `@SpringBootConfiguration` classes would otherwise make discovery ambiguous. A key subtlety: naming a plain `@Configuration` in `classes` does **not** enable component scanning or auto-configuration by itself — you get only the beans those classes declare or import. To keep auto-config, point `classes` at a class annotated with `@SpringBootApplication`/`@EnableAutoConfiguration`, or add those annotations to your test config.

code

java · 19 lines
java
@SpringBootTest(classes = { OrderService.class, PricingConfig.class })
class OrderServiceSliceTest {
    // Context contains ONLY OrderService + what PricingConfig declares/imports.
    // No component scan of com.myapp.**, no auto-configuration.
    @Autowired OrderService service;

    @Test void computesTotal() {
        assertThat(service.total(cart)).isEqualByComparingTo("42.00");
    }
}

// To keep auto-config while still overriding, name a Boot-annotated class:
@SpringBootTest(classes = TestApp.class)
class FullContextTest {
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan("com.myapp.order")
    static class TestApp {}
}

go deeper

for a junior

Know that classes lets you name the config explicitly.

for a middle

Explain that it skips discovery and that a plain @Configuration drops scanning + auto-config.

for a senior

Weigh leaner explicit config vs full context for speed and isolation; know the @ContextConfiguration relationship.

for a principal

Set team conventions for when to override, avoiding context-cache fragmentation from too many bespoke configs.

### What the attribute does `@SpringBootTest(classes = ...)` explicitly lists the component/configuration classes used to build the test `ApplicationContext`. When present, Spring Boot **skips** the `@SpringBootConfiguration` package-tree discovery entirely and uses exactly what you provide (plus whatever those classes `@Import`, scan, or enable). ### When to reach for it - **Leaner context:** the real `@SpringBootApplication` triggers auto-configuration for the whole app (data sources, security, messaging clients). If your test only needs a couple of beans, listing a small `@Configuration` builds a smaller, faster context. - **No reachable main class:** in a library or a module without a `@SpringBootApplication`, discovery would fail (`Unable to find a @SpringBootConfiguration`). `classes` gives it a target. - **Disambiguation:** if two `@SpringBootConfiguration` classes are in scope, discovery is ambiguous; naming one resolves it. - **Custom test wiring:** supply a test-specific config that swaps in fakes/stubs. ### The crucial gotcha: you lose the convention magic `@SpringBootApplication` bundles three things: `@SpringBootConfiguration` (+ `@Configuration`), `@ComponentScan`, and `@EnableAutoConfiguration`. If you point `classes` at a bare `@Configuration`, you get **only** the beans it declares/imports — **no** component scanning of your packages and **no** auto-configuration. Your `@Repository`, `@Service`, `@Controller` beans elsewhere won't be picked up unless the named config scans or imports them. To retain auto-config, either name a class carrying `@SpringBootApplication`/`@EnableAutoConfiguration`, or add those annotations to the test config class. ### Related knobs - `@ContextConfiguration(classes = ...)` (Spring TestContext, the lower-level mechanism) does the same explicit-config job; `@SpringBootTest`'s `classes` is the Boot-flavored front for it. - Nested `static @Configuration` / `@TestConfiguration` classes inside the test can supplement (not replace) the primary config; `@TestConfiguration` is *additive* and only applies when included. - `properties`/`args` on `@SpringBootTest` tune the environment but don't change which config is selected. ### Interview framing The expected insight is that `classes` is an escape hatch from convention, and that misusing it (naming a plain `@Configuration` and expecting a full app) silently produces a context missing your scanned beans and auto-configuration.

  • If you pass a plain @Configuration to classes, why might your @Service beans be missing from the context?
    Because naming a bare @Configuration bypasses discovery AND doesn't enable @ComponentScan. Only beans that config declares or explicitly imports/scans exist. Your @Service classes elsewhere are never scanned, so they're absent — you'd need the config to scan or import them, or to name a @ComponentScan-enabled class.
  • How does @SpringBootTest(classes=...) relate to @ContextConfiguration(classes=...)?
    @SpringBootTest's classes attribute is Spring Boot's convenience wrapper over the underlying Spring TestContext @ContextConfiguration mechanism. Both explicitly designate configuration classes and disable auto-discovery; @SpringBootTest layers Boot conventions (webEnvironment, properties, Boot bootstrapper) on top.

saying these in an interview costs you the question

  • Believing classes = MyConfig.class still runs component scanning and auto-configuration automatically
  • Confusing @TestConfiguration (additive) with classes (replaces discovery)
  • Thinking classes changes only the environment/properties, not which beans load

context