Починаючи з версії 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 на рівні класу.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ