skip to content

@ContextConfiguration & Context Loading

@ContextConfiguration declares which configuration builds the test's context, with hierarchies and initializers for more complex cases. Interviewers ask what actually gets loaded, because loading everything is the default failure mode.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What does @ContextConfiguration do, and how do its `classes` and `locations` attributes differ?

level: juniorimportance: must knowfreq 70%

answer

  1. classes = Java config, locations = XML/Groovy
  2. one style per declaration, not both
  3. empty -> nested @Configuration or <Test>-context.xml
  4. merged into MergedContextConfiguration = cache key
  5. TCF recipe, driven by SpringExtension

basics

~10 s

@ContextConfiguration tells the Spring TestContext Framework how to build the ApplicationContext for a test. classes points to @Configuration/component classes; locations (or value) points to XML or Groovy resource files.

solid answer

~40 s

@ContextConfiguration is a class-level annotation that declares how to load and configure the ApplicationContext used by an integration test. Its `classes` attribute lists Java @Configuration or component classes (annotation-based config), while `locations`/`value` lists XML or Groovy resource paths (`classpath:`/relative). You pick one style per level; mixing both in a single declaration isn't supported by the default loaders. If you specify neither, the framework auto-detects: it looks for static nested @Configuration classes, or an XML file named `<TestClass>-context.xml` beside the test. The resolved config is combined with active profiles, initializers, and the loader into a MergedContextConfiguration, which also becomes the context cache key so the same context is reused across tests.

code

java · 22 lines
java
// Java-based (component) configuration
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { AppConfig.class, TestBeans.class })
class OrderServiceTest {
    @Autowired OrderService service;
}

// XML / Groovy resource configuration
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = { "classpath:app-context.xml" })
class LegacyOrderServiceTest {
    @Autowired OrderService service;
}

// Convention: static nested @Configuration is auto-detected
@ExtendWith(SpringExtension.class)
@ContextConfiguration
class ConventionTest {
    @Configuration
    static class Config { @Bean OrderService svc() { return new OrderService(); } }
    @Autowired OrderService service;
}

go deeper

for a junior

Know classes = Java config, locations/value = XML/Groovy, and that it configures the test's ApplicationContext.

for a middle

Add default detection (nested @Configuration, <Test>-context.xml) and the merged-config context cache key.

for a senior

Discuss inheritance/merging of config from superclasses and the loader delegation that picks classes vs locations.

for a principal

Frame it around MergedContextConfiguration equality driving cache reuse and suite-level performance strategy.

## What it is `@ContextConfiguration` is a class-level annotation from `org.springframework.test.context`. It is the core of the **Spring TestContext Framework (TCF)** — it tells the framework *how* to build the `ApplicationContext` that your integration test runs against. It does not itself run anything; `@ExtendWith(SpringExtension.class)` (JUnit 5) or `SpringRunner` (JUnit 4) is what drives the TCF, and `@ContextConfiguration` supplies the recipe. (`@SpringBootTest` is a composed annotation that includes `@ContextConfiguration` under the hood, but auto-detection of Boot config classes is a separate concern.) ## Key attributes - **`classes`** — an array of `Class<?>` referencing Java-based configuration: `@Configuration` classes, `@Component` classes, or any class Spring can process as a bean source. This is *annotation-based* / *component-class* configuration, loaded by `AnnotationConfigContextLoader`. - **`locations`** (and its alias **`value`**) — an array of `String` resource paths to **XML** (`applicationContext.xml`) or **Groovy** (`context.groovy`) bean-definition files. Paths can be `classpath:`-prefixed, absolute (`/com/acme/beans.xml`), or relative to the test class's package. Loaded by `GenericXmlContextLoader` / `GenericGroovyXmlContextLoader`. - **`initializers`** — `ApplicationContextInitializer` classes run before context refresh. - **`loader`** — an explicit `ContextLoader`/`SmartContextLoader`. - **`inheritLocations` / `inheritInitializers`** — control whether config from superclass tests is merged (default `true`). - **`name`** — used only with `@ContextHierarchy` to identify a level. ## classes vs locations They are two mutually-distinct ways to describe the *same* thing — bean definitions: - `classes` = programmatic/annotation config (modern default). - `locations` = external XML/Groovy resource config (legacy but fully supported). A single `@ContextConfiguration` should use **one** of them. The default `DelegatingSmartContextLoader` inspects which attribute is populated and delegates to the matching concrete loader; it does **not** load both `classes` and `locations` together for one declaration. ## Default detection (specify neither) If you write `@ContextConfiguration` with no `classes` and no `locations`, the loaders attempt **convention-based detection**: - `AnnotationConfigContextLoader` scans the test class for **static nested `@Configuration` classes** and uses them. - `GenericXmlContextLoader` looks for an XML file named **`<FullyQualifiedTestClassName-with-slashes>-context.xml`** on the classpath (e.g. `com/acme/MyTest-context.xml`). ## MergedContextConfiguration & caching Whatever you declare is normalized into a **`MergedContextConfiguration`** object (locations + classes + initializers + active profiles + property sources + loader + parent). This object's equality is the **context cache key**: two tests with the same merged config **share one cached ApplicationContext**, which is the single biggest performance lever in a Spring test suite. `@DirtiesContext` evicts a context from the cache. ## Gotchas - Relative XML paths are relative to the **test class package**, not the working directory. - Empty `@ContextConfiguration` with no nested config and no matching XML fails to load a context. - Config on a superclass test is **inherited and merged** by default — surprising if you didn't expect it (`inheritLocations=false` to override). - `classes` referencing a plain POJO with no stereotype still registers it as a bean (component-class semantics), which can surprise people expecting only `@Configuration`.

  • If you provide neither classes nor locations, how does Spring decide what to load?
    It falls back to convention: AnnotationConfigContextLoader looks for static nested @Configuration classes on the test, and GenericXmlContextLoader looks for a classpath XML named `<TestClass>-context.xml`. If nothing is found, context loading fails.
  • Why does using the same @ContextConfiguration across many tests speed up the suite?
    The merged config becomes a cache key; identical configs share one ApplicationContext instance, so it's built once and reused instead of rebuilt per test class.

saying these in an interview costs you the question

  • Thinking @ContextConfiguration executes/runs the test rather than describing the context recipe
  • Claiming you can freely mix `classes` and `locations` in one declaration and both load together
  • Believing relative XML paths are resolved from the working directory rather than the test's package

context

open as a page

How does the TestContext Framework resolve which ContextLoader to use, and what is SmartContextLoader / DelegatingSmartContextLoader?

level: middleimportance: should knowfreq 40%

basics

~10 s

If you don't set loader, Spring uses DelegatingSmartContextLoader by default. It delegates to AnnotationConfigContextLoader for classes and GenericXmlContextLoader/GenericGroovyXmlContextLoader for locations, picking whichever matches your declaration.

open as a page

What is ApplicationContextInitializer and how do you use the `initializers` attribute of @ContextConfiguration?

level: seniorimportance: should knowfreq 35%

basics

~20 s

An ApplicationContextInitializer is a callback that runs against the ConfigurableApplicationContext just before it's refreshed. You register it via @ContextConfiguration(initializers = ...) to programmatically tweak the context — add property sources, activate profiles, or register bean definitions.

open as a page

What is @ContextHierarchy and when would you use parent/child ApplicationContexts in tests?

level: seniorimportance: should knowfreq 30%

basics

~10 s

@ContextHierarchy declares multiple @ContextConfiguration levels that form a parent-child ApplicationContext chain. Child contexts can see parent beans but not vice versa — useful for splitting shared infrastructure (parent) from a web layer (child).

open as a page

How does @ContextConfiguration inheritance/merging combine with the context cache key, and how do you control it?

level: principalimportance: should knowfreq 25%

basics

~20 s

All declared config (classes, locations, initializers, active profiles, property sources, loader, parent) is combined into a MergedContextConfiguration. Its equality is the cache key, so identical configs share one context. Superclass config is merged by default; inheritLocations/inheritInitializers=false to override.

open as a page