Починаючи з версії 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:

Java
@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);
    }
}
  1. Анотуємо тестовий клас за допомогою @RecordApplicationEvents.
  2. Впроваджуємо екземпляр ApplicationEvents для поточного тесту.
  3. Використовуємо API-інтерфейс ApplicationEvents, щоб підрахувати, скільки подій OrderSubmitted було опубліковано.
Kotlin
@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)
    }
}
  1. Анотуємо тестовий клас за допомогою @RecordApplicationEvents.
  2. Впроваджуємо екземпляр ApplicationEvents для поточного тесту.
  3. Використовуємо 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 на рівні класу.