Spring предоставляет следующие реализации TestExecutionListener, которые регистрируются по умолчанию, точно в следующем порядке:

  • ServletTestExecutionListener: Конфигурирует объекты-имитации API-интерфейса сервлетов для WebApplicationContext.

  • DirtiesContextBeforeModesTestExecutionListener: Обрабатывает аннотацию@DirtiesContext для режимов "перед".

  • ApplicationEventsTestExecutionListener: Обеспечивает поддержку ApplicationEvents.

  • DependencyInjectionTestExecutionListener: Обеспечивает внедрение зависимостей для тестового экземпляра.

  • DirtiesContextTestExecutionListener: Обрабатывает аннотацию@DirtiesContext для режимов "после".

  • TransactionalTestExecutionListener: Обеспечивает транзакционное выполнение тестов с семантикой отката по умолчанию.

  • SqlScriptsTestExecutionListener: Выполняет SQL-скрипты, сконфигурированные с помощью аннотации@Sql.

  • EventPublishingTestExecutionListener: Публикует cобытия выполнения теста
    в ApplicationContext.

Регистрация реализаций TestExecutionListener

Вы можете зарегистрировать реализации TestExecutionListener для тестового класса и его подклассов с помощью аннотации @TestExecutionListeners. Подробности и примеры смотрите в подразделе, посвященном поддержке аннотаций, и javadoc по аннотации @TestExecutionListeners .

Автоматическое обнаружение реализаций TestExecutionListener по умолчанию

Регистрация реализаций TestExecutionListener с помощью аннотации @TestExecutionListeners подходит для специальных слушателей, которые используются в ограниченных сценариях тестирования. Однако регистрация может стать затруднительной, если специальный слушатель необходимо использовать во всем тестовом комплекте. Эта проблема решается благодаря поддержке автоматического обнаружения реализаций TestExecutionListener по умолчанию через механизм SpringFactoriesLoader.

В частности, модуль spring-test объявляет все реализации TestExecutionListener по умолчанию в ключе org.springframework.test.context.TestExecutionListener в файле свойств META-INF/spring.factories. Сторонние фреймворки и разработчики могут вносить свои собственные реализации TestExecutionListener в список слушателей по умолчанию таким же образом через собственный файл свойств META-INF/spring.factories.

Упорядочивание реализаций TestExecutionListener

Если фреймворк TestContext обнаруживает реализации TestExecutionListener по умолчанию через вышеупомянутый механизм SpringFactoriesLoader, созданные экземпляры слушателей сортируются с помощью AnnotationAwareOrderComparator их Spring, который учитывает интерфейс Ordered из Spring и аннотацию @Order для упорядочивания. AbstractTestExecutionListener и все реализации TestExecutionListener по умолчанию, предоставляемые Spring, реализуют Ordered с соответствующими значениями. Поэтому сторонним фреймворкам и разработчикам следует удостовериться, что их реализации TestExecutionListener по умолчанию регистрируются в правильном порядке, реализуя Ordered или объявляя аннотацию @Order. Смотрите javadoc по методам getOrder() основных реализаций TestExecutionListener по умолчанию для получения более подробной информации о том, какие значения присваиваются каждому основному слушателю.

Объединение реализаций TestExecutionListener

Если специальный слушатель TestExecutionListener зарегистрирован через аннотацию @TestExecutionListeners, слушатели по умолчанию не регистрируются. В наиболее распространенных сценариях тестирования это фактически вынуждает разработчика вручную объявлять все слушатели по умолчанию в дополнение к любым специальным слушателям. Следующий листинг демонстрирует этот стиль конфигурации:

Java
@ContextConfiguration
@TestExecutionListeners({
    MyCustomTestExecutionListener.class,
    ServletTestExecutionListener.class,
    DirtiesContextBeforeModesTestExecutionListener.class,
    DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    SqlScriptsTestExecutionListener.class
})
class MyTest {
    // тело класса...
}
Kotlin
@ContextConfiguration
@TestExecutionListeners(
    MyCustomTestExecutionListener::class,
    ServletTestExecutionListener::class,
    DirtiesContextBeforeModesTestExecutionListener::class,
    DependencyInjectionTestExecutionListener::class,
    DirtiesContextTestExecutionListener::class,
    TransactionalTestExecutionListener::class,
    SqlScriptsTestExecutionListener::class
)
class MyTest {
    // тело класса...
}

Сложность этого подхода заключается в том, что он требует от разработчика точного знания того, какие слушатели зарегистрированы по умолчанию. Более того, набор слушателей по умолчанию может меняться от версии к версии – например, слушатель SqlScriptsTestExecutionListener был представлен в Spring Framework 4.1, а DirtiesContextBeforeModesTestExecutionListener был представлен в Spring Framework 4.2. Более того, сторонние фреймворки, такие как Spring Boot и Spring Security, регистрируют свои собственные реализации TestExecutionListener по умолчанию, используя вышеупомянутый механизм автоматического обнаружения.

Чтобы избежать необходимости знать и повторно объявлять все слушатели по умолчанию, можно установить атрибут mergeMode аннотации @TestExecutionListeners в MergeMode.MERGE_WITH_DEFAULTS. MERGE_WITH_DEFAULTS указывает, что локально объявленные слушатели должны быть объединены со слушателями по умолчанию. Алгоритм объединения обеспечивает удаление дубликатов из списка и сортировку полученного набора объединенных слушателей в соответствии с семантикой AnnotationAwareOrderComparator, как описано в разделе "Упорядочивание реализаций TestExecutionListener". Если слушатель реализует Ordered или помечен аннотацией @Order, он может влиять на позицию, в которой он объединяется с слушателями по умолчанию. В противном случае локально объявленные слушатели добавляются к списку слушателей по умолчанию при объединении.

Например, если класс MyCustomTestExecutionListener в предыдущем примере сконфигурирует свое значение order (например, 500) так, что оно будет меньше значения очередности ServletTestExecutionListener (которое равняется 1000), то MyCustomTestExecutionListener может быть автоматически объединен со списком значений по умолчанию перед ServletTestExecutionListener, а предыдущий пример можно будет заменить следующим:

Java
@ContextConfiguration
@TestExecutionListeners(
    listeners = MyCustomTestExecutionListener.class,
    mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
    // тело класса...
}
Kotlin
@ContextConfiguration
@TestExecutionListeners(
        listeners = [MyCustomTestExecutionListener::class],
        mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
    // тело класса...
}