Интеграционное тестирование в Spring: TestContext Framework, кэширование контекста

Как только TestContext framework загружает ApplicationContext (или WebApplicationContext) для теста, этот контекст кэшируется и повторно используется для всех последующих тестов, которые объявляют ту же уникальную конфигурацию контекста в одном и том же наборе тестов. Чтобы понять, как работает кэширование, важно понимать, что имеется в виду под "уникальным" и "набором тестов".

ApplicationContext можно однозначно идентифицировать по комбинации параметров конфигурации, которые используются для его загрузки. Следовательно, уникальная комбинация параметров конфигурации используется для генерации ключа, под которым кэшируется контекст. TestContext framework использует следующие параметры конфигурации для создания ключа кэша контекста:

  • locations (из @ContextConfiguration)
  • classes (из @ContextConfiguration)
  • contextInitializerClasses (из @ContextConfiguration)
  • contextCustomizers (из ContextCustomizerFactory) - это включает методы @DynamicPropertySource, а также различные функции из поддержки тестирования Spring Boot, такие как @MockBean и @SpyBean.
  • contextLoader (из @ContextConfiguration)
  • parent (из @ContextHierarchy)
  • activeProfiles (из @ActiveProfiles)
  • propertySourceLocations (из @TestPropertySource)
  • propertySourceProperties (из @TestPropertySource)
  • resourceBasePath (из @WebAppConfiguration)

Например, если TestClassA указывает {"app-config.xml", "test-config.xml"} для атрибута location (или value) @ContextConfiguration, TestContext framework загружает соответствующий ApplicationContext и сохраняет его в статическом кэше контекста под ключом, который основан исключительно на этих местоположениях. Итак, если TestClassB также определяет {"app-config.xml", "test-config.xml"} для своих местоположений (явно или неявно через наследование), но не определяет @WebAppConfiguration, другой ContextLoader, разные активные профили, разные инициализаторы контекста, разные источники тестовых свойств или другой родительский контекст, то один и тот же ApplicationContext используется обоими тестовыми классами. Это означает, что затраты на установку для загрузки контекста приложения производятся только один раз (для каждого набора тестов), а последующее выполнение теста происходит намного быстрее.

Наборы тестов и разветвленные процессы

Spring TestContext framework хранит контексты приложений в статическом кэше. Это означает, что контекст буквально хранится в статической переменной. Другими словами, если тесты выполняются в отдельных процессах, статический кэш очищается между каждым выполнением теста, что фактически отключает механизм кэширования.

Чтобы воспользоваться механизмом кэширования, все тесты должны выполняться в рамках одного процесса или набора тестов. Это может быть достигнуто путем выполнения всех тестов как группы в среде IDE. Точно так же при выполнении тестов с помощью платформы сборки, такой как Ant, Maven или Gradle, важно убедиться, что среда сборки не разветвляется между тестами. Например, если forkMode для подключаемого модуля Maven Surefire установлен на always или pertest, TestContext framework не может кэшировать контексты приложения между тестовыми классами, и в результате процесс сборки будет выполняться значительно медленнее.

Размер кэша контекста ограничен максимальным размером по умолчанию, равным 32. Когда достигается максимальный размер, для удаления и закрытия устаревших контекстов используется политика вытеснения наименее недавно использовавшейся (LRU). Вы можете настроить максимальный размер из командной строки или сценария сборки, установив системное свойство JVM с именем spring.test.context.cache.maxSize. В качестве альтернативы вы можете установить то же свойство программно, используя SpringProperties API.

Поскольку наличие большого количества контекстов приложения, загруженных в рамках данного набора тестов, может привести к чрезмерно длительному запуску набора, часто бывает полезно знать, сколько контекстов было загружено и кэшировано. Чтобы просмотреть статистику для базового кэша контекста, вы можете установить уровень журнала для категории ведения журнала org.springframework.test.context.cache на DEBUG.

В том маловероятном случае, когда тест повреждает контекст приложения и требует перезагрузки (например, путем изменения определения компонента или состояния объекта приложения), вы можете аннотировать свой тестовый класс или тестовый метод с помощью @DirtiesContext. Это указывает Spring удалить контекст из кэша и перестроить контекст приложения перед запуском следующего теста, для которого требуется тот же контекст приложения. Обратите внимание, что поддержка аннотации @DirtiesContext обеспечивается DirtiesContextBeforeModesTestExecutionListener и DirtiesContextTestExecutionListener, которые включены по умолчанию.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки