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
, слушатели по умолчанию не регистрируются. В наиболее распространенных сценариях тестирования это фактически вынуждает разработчика вручную объявлять все слушатели по умолчанию в дополнение к любым специальным слушателям. Следующий листинг демонстрирует этот стиль конфигурации:
@ContextConfiguration
@TestExecutionListeners({
MyCustomTestExecutionListener.class,
ServletTestExecutionListener.class,
DirtiesContextBeforeModesTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
SqlScriptsTestExecutionListener.class
})
class MyTest {
// тело класса...
}
@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
, а предыдущий пример можно будет заменить следующим:
@ContextConfiguration
@TestExecutionListeners(
listeners = MyCustomTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
// тело класса...
}
@ContextConfiguration
@TestExecutionListeners(
listeners = [MyCustomTestExecutionListener::class],
mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
// тело класса...
}