Ответ
Кэширование тестового контекста Spring — это механизм фреймворка Spring Test, который переиспользует один и тот же экземпляр ApplicationContext между несколькими тестовыми классами. Это значительно ускоряет выполнение набора интеграционных тестов, так как процесс создания контекста (сканирование компонентов, настройка бинов, проксирование) выполняется только один раз.
Как это работает: Spring вычисляет уникальный ключ кэша на основе:
- Местоположения конфигурации (
@ContextConfiguration). - Параметров контекста (активные профили
@ActiveProfiles, загрузчики). - Параметров самого тестового класса. Если ключ совпадает с уже загруженным контекстом, он переиспользуется.
Пример:
// TestClassA.java
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class})
@ActiveProfiles("test")
public class TestClassA {
@Test
void test1() { /* Использует кэшированный контекст */ }
}
// TestClassB.java (использует тот же контекст)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class}) // Та же конфигурация
@ActiveProfiles("test") // Тот же профиль
public class TestClassB {
@Test
void test2() { /* Переиспользует контекст из TestClassA */ }
}
Управление кэшем:
- Сброс контекста: Используйте
@DirtiesContext, если тест модифицирует состояние контекста (например, заменяет бин-заглушку), чтобы последующие тесты получили свежий экземпляр.@Test @DirtiesContext // Помечает контекст как "грязный" после этого метода void testThatModifiesContext() { ... } - По умолчанию кэширование включено. Это одна из главных причин, почему Spring-тесты быстрее, чем ручное создание контекста для каждого класса.
Ответ 18+ 🔞
А, слушай, смотри, это ж просто пиздец какая полезная штука, если ты, конечно, не любитель ждать, пока твои тесты выполняются до второго пришествия. Кэширование контекста в Spring Test — это когда фреймворк, такой хитрожопый, не создаёт тебе новый ApplicationContext для каждого тестового класса, а юзает один и тот же, уже готовый.
Ну, то есть как оно, блядь, работает: Представь, Spring — это такой скряга-бухгалтер. Перед тем как запустить тесты, он высчитывает уникальный ключик для контекста. Смотрит на всё: на твои конфигурационные классы, на активные профили, на всякие там параметры. Если ключ совпадает с тем, что уже лежит в его загашнике (в кэше), он не парится и подсовывает тебе старый, уже настроенный контекст. Экономия времени — просто овердохуищная, потому что сканирование, создание бинов и прочая магия происходит один раз, а не для каждой тестовой папки.
Вот, смотри, как это в коде выглядит, епта:
// TestClassA.java
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class})
@ActiveProfiles("test")
public class TestClassA {
@Test
void test1() { /* Использует кэшированный контекст */ }
}
// TestClassB.java (использует тот же контекст)
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class}) // Та же конфигурация
@ActiveProfiles("test") // Тот же профиль
public class TestClassB {
@Test
void test2() { /* Переиспользует контекст из TestClassA */ }
}
Видишь? Оба класса тырят контекст из одного и того же ведра. Spring его создал для TestClassA, а TestClassB уже пришёл на готовенькое.
Но есть, блядь, нюанс, как говорится:
Иногда тест такой подлый, что начинает в контексте шаманить — подменяет бины, меняет состояние. Для таких случаев есть аннотация @DirtiesContext. Она как красная тряпка: после такого теста Spring помечает контекст как «грязный» и на следующий запрос выдаёт свеженький, чтобы никто не отравился.
@Test
@DirtiesContext // Помечает контекст как "грязный" после этого метода
void testThatModifiesContext() { ... }
А так-то по умолчанию эта фича включена. И это, блядь, одна из главных причин, почему Spring-тесты не тормозят как черепаха в патруле. Вместо того чтобы каждый раз строить дворец с нуля, они просто заходят в уже построенный. Удобно, чё.