The full picture
- Measure first: run with
logging.level.org.springframework.test.context.cache=DEBUG— it prints cache hits/misses and context count. >5 distinct contexts for one service should raise eyebrows. - Standardize the key: one
AbstractIntegrationTest(annotations, containers, profile) that all ITs extend — every deviation is a review conversation. - Mock hygiene: each unique @MockitoBean combination = new context. Group mocks into shared
@TestConfigurationclasses; or replace boundary mocks with singleton fakes/WireMock so the context stays identical. - @DirtiesContext is a fire alarm, not a doorstop: it exists for tests that genuinely corrupt global state; used as a flakiness bandaid it turns O(1) contexts into O(n).
- Parallelize what's parallel-safe: JUnit parallel execution + independent data (unique keys per test) — after the cache is fixed, not before.
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("it")
@Import(SharedTestBeans.class) // ALL common fakes live here
@Testcontainers
public abstract class AbstractIT {
@Container @ServiceConnection
static final PostgreSQLContainer<?> DB = Containers.postgres(); // singleton
}
class OrderFlowIT extends AbstractIT { … } // cache HIT
class RefundFlowIT extends AbstractIT { … } // cache HIT — same key, same context