Починаючи з версії Spring Framework 5.3.3, фреймворк TestContext забезпечує підтримку запису подій програми,
опублікованих у ApplicationContext
, щоб можна було щодо цих подій виконувати твердження в тестах. Всі
події, опубліковані під час виконання одного тесту, доступні через API-інтерфейс ApplicationEvents
,
який дозволяє обробляти події як java.util.Stream
.
Щоб використовувати ApplicationEvents
у своїх тестах, зроби таке.
-
Переконайся, що твій тестовий клас анотований або мета-анотований за допомогою
@RecordApplicationEvents
. -
Переконайся, що
ApplicationEventsTestExecutionListener
зареєстровано. Зверни увагу, щоApplicationEventsTestExecutionListener
зареєстровано за замовчуванням, а реєструвати його вручну потрібно лише в тому випадку, якщо у тебе є спеціальна конфігурація через анотацію@TestExecutionListeners
, яка не включає слухачів за замовчуванням. -
Анотуй поле типу
ApplicationEvents
за допомогою анотації@Autowired
та використовуй цей екземплярApplicationEvents
у твоїх тестових методах та методах життєвого циклу (наприклад, методи, позначені анотаціями@BeforeEach
та@AfterEach
, в JUnit Jupiter).-
При використанні розширення SpringExtension для JUnit Jupiter можна оголосити параметр методу типу
ApplicationEvents
у тестовому методі або методі життєвого циклу як альтернативу полю, анотованому@Autowired
, у тестовому класі.
-
Наступний тестовий клас використовує SpringExtension
для JUnit Jupiter та AssertJ для затвердження типів подій програми, що
публікуються під час виклику методу в компоненті, керованому Spring:
@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
class OrderServiceTests {
@Autowired
OrderService orderService;
@Autowired
ApplicationEvents events;
@Test
void submitOrder() {
// Викликаємо метод OrderService, який публікує подію
orderService.submitOrder(new Order(/*...*/));
// Перевіряємо, щоб подія OrderSubmitted була опублікована
long numEvents = events.stream(OrderSubmitted.class).count();
assertThat(numEvents).isEqualTo(1);
}
}
- Анотуємо тестовий клас за допомогою
@RecordApplicationEvents
. - Впроваджуємо екземпляр
ApplicationEvents
для поточного тесту. - Використовуємо API-інтерфейс
ApplicationEvents
, щоб підрахувати, скільки подійOrderSubmitted
було опубліковано.
@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
class OrderServiceTests {
@Autowired
lateinit var orderService: OrderService
@Autowired
lateinit var events: ApplicationEvents
@Test
fun submitOrder() {
// Викликаємо метод OrderService, який публікує подію
orderService.submitOrder(Order(/* ... */))
// Перевіряємо, щоб подія OrderSubmitted була опублікована
val numEvents = events.stream(OrderSubmitted::class).count()
assertThat(numEvents).isEqualTo(1)
}
}
- Анотуємо тестовий клас за допомогою
@RecordApplicationEvents
. - Впроваджуємо екземпляр
ApplicationEvents
для поточного тесту. - Використовуємо API-інтерфейс
ApplicationEvents
, щоб підрахувати, скільки подійOrderSubmitted
було опубліковано.
Див. javadoc ApplicationEvents
для отримання додаткової інформації про API-інтерфейс ApplicationEvents
.
Події виконання тесту
Слухач EventPublishingTestExecutionListener
, представлений у Spring Framework 5.2, пропонує
альтернативний підхід до реалізації спеціального TestExecutionListener
. Компоненти в ApplicationContext
тесту можуть прослуховувати такі події, що публікуються EventPublishingTestExecutionListener
, кожна з
яких відповідає методу в API-інтерфейсі TestExecutionListener
.
-
BeforeTestClassEvent
-
PrepareTestInstanceEvent
-
BeforeTestMethodEvent
-
BeforeTestExecutionEvent
-
AfterTestExecutionEvent
-
AfterTestMethodEvent
-
AfterTestClassEvent
Ці події можуть бути використані з різних причин, наприклад, для скидання бінів-імітацій або відстеження виконання
тестів. Однією з переваг споживання подій виконання тесту замість реалізації спеціального TestExecutionListener
є те, що події виконання тесту можуть бути спожиті будь-яким бином Spring, зареєстрованим у тестовому ApplicationContext
,
і такі біни можуть безпосередньо скористатися використанням залежностей та іншими функціями
ApplicationContext
. На відміну від цього, TestExecutionListener
не є біном у ApplicationContext
.
Слухач EventPublishingTestExecutionListener
зареєстрований за замовчуванням; однак він публікує
події лише в тому випадку, якщо ApplicationContext
вже завантажено. Це запобігає непотрібному або
надто ранньому завантаженню ApplicationContext
.
Отже, подію BeforeTestClassEvent
буде опубліковано лише після того, як
ApplicationContext
буде завантажено іншим TestExecutionListener
. Наприклад, при наборі
реалізацій TestExecutionListener
, зареєстрованих за замовчуванням, подія
BeforeTestClassEvent
не буде опублікована для першого тестового класу, який використовує певний
тестовий ApplicationContext
, але подія BeforeTestClassEvent
буде опублікована
для будь-якого наступного тестового класу в тому ж тестовому комплекті, який використовує той же тестовий ApplicationContext
,
оскільки контекст вже буде завантажений при виконанні наступних тестових класів (якщо контекст не був видалений
з ContextCache
через анотацію @DirtiesContext
або політику витіснення при досягненні
максимального розміру).
Якщо потрібно, щоб подія BeforeTestClassEvent
завжди публікувалася для кожного тестового класу,
необхідно зареєструвати TestExecutionListener
, який завантажує ApplicationContext
у
зворотному виклику beforeTestClass
, і цей TestExecutionListener
має бути
зареєстрований перед EventPublishingTestExecutionListener
.
Аналогічно, якщо анотація @DirtiesContext
використовується для видалення
ApplicationContext
з кешу контексту після останнього тестового методу в даному тестовому класі,
подія AfterTestClassEvent
не буде опубліковано для цього тестового класу.
Щоб прослуховувати події виконання тесту, бін Spring може вибрати реалізацію інтерфейсу org.springframework.context.ApplicationListener
.
Крім того, методи слухачів можуть бути анотовані @EventListener
та налаштовані на прослуховування
одного з конкретних типів подій, перерахованих вище (див. Слухачі
(одержувачі) подій на основі анотацій).
У зв'язку з популярністю цього підходу Spring надає наступні спеціальні анотації @EventListener
для
спрощення реєстрації слухачів подій виконання тесту. Ці анотації знаходяться в пакеті org.springframework.test.context.event.annotation
.
-
@BeforeTestClass
-
@PrepareTestInstance
-
@BeforeTestMethod
-
@BeforeTestExecution
-
@AfterTestExecution
-
@AfterTestMethod
-
@AfterTestClass
Обробка винятків
За замовчуванням, якщо слухач подій виконання тесту генерує виняток при споживанні події, цей виняток передається у
базовий тестовий фреймворк, що використовується (наприклад, JUnit або TestNG). Наприклад, якщо використання події
BeforeTestMethodEvent
призводить до виникнення винятку, то відповідний тестовий метод у результаті
винятку завершиться помилкою. І навпаки, якщо асинхронний слухач подій виконання тесту генерує виняток, він не
поширюється до базового тестового фреймворку. Для отримання більш детальної інформації про асинхронну обробку
винятків звернися до javadoc за @EventListener
на рівні класу.
Асинхронні слухачі
Якщо потрібно, щоб певний слухач подій виконання тесту обробляв події асинхронно, можна використовувати звичайну підтримку анотації
@Async
із Spring.
Для отримання більш детальної інформації звернися до javadoc за @EventListener
на рівні класу.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ