What is the Spring TestContext application-context cache, and why does it exist?
answer
- Static JVM-wide context cache
- Build once, reuse across test classes
- Keyed on merged config
- Startup is the expensive part
- Default 32, LRU
basics
~10 sSpring starts the application context once and reuses (caches) it across test classes that ask for the same configuration, instead of rebuilding it per test. This makes the whole test suite much faster.
solid answer
~40 sThe Spring TestContext Framework caches loaded ApplicationContexts across the entire test suite (per JVM/test run) so a context is built once and reused by every test that requests an identical configuration. Building a Spring context — component scanning, bean creation, autoconfiguration, connecting to a database — is expensive, so without caching every test class would pay that cost again. The cache is keyed on the merged test configuration, so two test classes with the same @ContextConfiguration/@SpringBootTest classes, profiles, and properties share one context. The cache is static and lives for the duration of the test run; it is not cleared between test classes unless something forces eviction (e.g. @DirtiesContext). Understanding it is the difference between a suite that runs in seconds and one that reloads Spring dozens of times.
code
java · 13 lines// Both test classes below resolve to the SAME cache key
// (same config class, no profiles/props/mocks differences)
// => Spring builds ONE context and reuses it for both.
@SpringJUnitConfig(AppConfig.class)
class OrderServiceTest {
@Test void placesOrder() { /* ... */ }
}
@SpringJUnitConfig(AppConfig.class)
class InventoryServiceTest {
@Test void reserves() { /* ... */ } // reuses cached context
}go deeper
Know the one-liner: Spring caches and reuses the context across tests for speed instead of rebuilding it each time.
Explain that reuse is keyed on the merged configuration and that shared singletons can cause state leakage between tests.
Discuss the ContextCache/CacheAwareContextLoaderDelegate mechanics, default maxSize 32, LRU eviction, and how to keep the number of distinct contexts small.
Frame cache design as a suite-wide performance and isolation contract: minimize distinct keys, standardize base test config, reserve @DirtiesContext for genuine corruption.
## The problem it solves Starting a Spring `ApplicationContext` is slow: Spring scans for `@Component`/`@Configuration` classes, instantiates and wires all beans, runs Spring Boot autoconfiguration, opens connection pools, runs Flyway/Liquibase, etc. If every `@SpringBootTest` or `@SpringJUnitConfig` test class rebuilt the context from scratch, a suite of 200 test classes could restart Spring 200 times. ## What the cache is The **Spring TestContext Framework (TCF)** keeps a **static, JVM-wide cache** of loaded contexts, managed by `org.springframework.test.context.cache.ContextCache` (default impl `DefaultContextCache`) and coordinated by the `CacheAwareContextLoaderDelegate`. When a test needs a context, the framework computes a **cache key** from the test's *merged* configuration (`MergedContextConfiguration`). If a context with that key already exists, it is **reused**; otherwise a new one is built and **stored** under that key. Because the cache is static, it survives across test classes within the same test run/JVM — that is the whole point. Two unrelated test classes that resolve to the **same** configuration will share **one physical context instance** (same singleton beans, same connection pool). ## Why it matters day to day - **Speed:** the dominant lever on suite runtime. A well-cached suite may load only a handful of distinct contexts total. - **Correctness:** because the *same* context (and its singleton beans) is shared, tests that mutate shared bean state or global data can leak into each other. Spring provides `@DirtiesContext` to force eviction when a test genuinely corrupts the context. - **Cache misses hurt:** anything that changes the cache key (different `@ActiveProfiles`, different `@TestPropertySource`, adding `@MockBean`/`@MockitoBean`, `@DynamicPropertySource`) produces a *new* context, multiplying startup cost. A common performance regression is accidentally creating many near-identical contexts. ## Key facts - Enabled automatically — you don't turn it on. - Default maximum number of cached contexts is **32**, evicted **LRU** (`spring.test.context.cache.maxSize`). - Rebuilding is triggered only by a new cache key or by explicit eviction (`@DirtiesContext`). ## When to think about it Any time your suite feels slow, or a test mysteriously passes alone but fails in the suite (shared-state leak), the context cache is the first thing to reason about.
- Is the cache per test class or shared across the whole suite?Shared across the whole test run within a JVM. It's a static cache, so any test class in the run whose merged configuration produces the same key reuses the already-loaded context.
- A test passes in isolation but fails when run with the suite. How does the cache explain that?The failing test likely shares a cached context (and its singleton beans / DB state) with an earlier test that mutated shared state. The fix is proper cleanup, transactional rollback, or @DirtiesContext on the offending test.
saying these in an interview costs you the question
- Thinking Spring rebuilds the context for every test method or every test class
- Believing the cache is per-thread or per-class rather than a static JVM-wide cache
- Not knowing that cached contexts share singleton bean state, so tests can leak into each other