Рубрики
Без рубрики

Весенний тестовый список

Краткий и практический обзор тестового списка Spring.

Автор оригинала: Priyesh Mashelkar.

1. Обзор

Обычно мы используем аннотации JUnit, такие как @beforeach, @afterEach, @beforeAll, и @AfterAll, для организации жизненного цикла тестов, но иногда этого недостаточно, особенно когда мы работаем с фреймворком Spring.

Вот где пригодится Spring TestExecutionListener .

В этом уроке мы увидим, что предлагает TestExecutionListener , прослушиватели по умолчанию, предоставляемые Spring, и как реализовать пользовательский TestExecutionListener .

2. Интерфейс TestExecutionListener

Во-первых, давайте посетим интерфейс TestExecutionListener :

public interface TestExecutionListener {
    default void beforeTestClass(TestContext testContext) throws Exception {};
    default void prepareTestInstance(TestContext testContext) throws Exception {};
    default void beforeTestMethod(TestContext testContext) throws Exception {};
    default void afterTestMethod(TestContext testContext) throws Exception {};
    default void afterTestClass(TestContext testContext) throws Exception {};
}

Реализации этого интерфейса могут получать события на различных этапах выполнения теста. Следовательно, каждому из методов в интерфейсе передается Тестовый контекст объект.

Этот объект TestContext содержит информацию о контексте Spring и целевом тестовом классе и методах. Эта информация может быть использована для изменения поведения тестов или расширения их функциональности.

Теперь давайте быстро рассмотрим каждый из этих методов:

  • afterTestClass – после обработки тестового класса после выполнения всех тестов внутри класса
  • afterTestExecution – после обработки теста сразу после выполнения метода тестирования в предоставленном контексте теста
  • afterTestMethod – после обработки теста после выполнения обратных вызовов после жизненного цикла базовой платформы тестирования
  • beforeTestClass – предварительная обработка тестового класса перед выполнением всех тестов внутри класса
  • beforeTestExecution – предварительная обработка теста непосредственно перед выполнением метода теста в предоставленном контексте теста
  • beforeTestMethod – предварительная обработка теста перед выполнением обратных вызовов до жизненного цикла базовой платформы тестирования
  • prepareTestInstance – подготавливает тестовый экземпляр предоставленного тестового контекста

Стоит отметить, что этот интерфейс предоставляет пустые реализации по умолчанию для всех методов. Следовательно, конкретные реализации могут переопределять только те методы, которые подходят для данной задачи.

3. Тестовые списки по умолчанию Spring

По умолчанию Spring предоставляет некоторые реализации TestExecutionListener из коробки.

Давайте быстро рассмотрим каждый из них:

  • ServletTestExecutionListener – настраивает насмешки API сервлета для WebApplicationContext
  • DirtiesContextBeforeModesTestExecutionListener – обрабатывает аннотацию @DirtiesContext для режимов “до”
  • DependencyInjectionTestExecutionListener – обеспечивает внедрение зависимостей для тестового экземпляра
  • Dirtiescontextextexecutionlistener – обрабатывает аннотацию @DirtiesContext для режимов “после”
  • TransactionalTestExecutionListener – обеспечивает выполнение транзакционного теста с семантикой отката по умолчанию
  • SqlScriptsTestExecutionListener – запускает сценарии SQL, настроенные с использованием аннотации @Sql

Эти слушатели предварительно регистрируются точно в указанном порядке. Мы увидим больше о порядке, когда создадим пользовательский TestExecutionListener .

4. Использование пользовательского TestExecutionListener

Теперь давайте определим пользовательский TestExecutionListener :

public class CustomTestExecutionListener implements TestExecutionListener, Ordered {
    private static final Logger logger = LoggerFactory.getLogger(CustomTestExecutionListener.class);
    
    public void beforeTestClass(TestContext testContext) throws Exception {
        logger.info("beforeTestClass : {}", testContext.getTestClass());
    }; 
    
    public void prepareTestInstance(TestContext testContext) throws Exception {
        logger.info("prepareTestInstance : {}", testContext.getTestClass());
    }; 
    
    public void beforeTestMethod(TestContext testContext) throws Exception {
        logger.info("beforeTestMethod : {}", testContext.getTestMethod());
    }; 
    
    public void afterTestMethod(TestContext testContext) throws Exception {
        logger.info("afterTestMethod : {}", testContext.getTestMethod());
    }; 
    
    public void afterTestClass(TestContext testContext) throws Exception {
        logger.info("afterTestClass : {}", testContext.getTestClass());
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    };
}

Для простоты все, что делает этот класс, – это регистрирует некоторую информацию о Тестовом контексте .

4.1. Регистрация пользовательского прослушивателя с помощью @TestExecutionListeners

Теперь давайте используем этот слушатель в нашем тестовом классе. Для этого мы зарегистрируем его с помощью аннотации @TestExecutionListeners :

@RunWith(SpringRunner.class)
@TestExecutionListeners(value = {
  CustomTestExecutionListener.class,
  DependencyInjectionTestExecutionListener.class
})
@ContextConfiguration(classes = AdditionService.class)
public class AdditionServiceUnitTest {
    // ...
}

Важно отметить, что использование аннотации отменит регистрацию всех прослушивателей по умолчанию . Следовательно, мы добавили DependencyInjectionTestExecutionListener явно, чтобы мы могли использовать автоматическую проводку в нашем тестовом классе.

Если нам понадобятся какие-либо другие прослушиватели по умолчанию, нам придется указать каждого из них. Но мы также можем использовать свойство merge Mode аннотации:

@TestExecutionListeners(
  value = { CustomTestExecutionListener.class }, 
  mergeMode = MergeMode.MERGE_WITH_DEFAULTS)

Здесь MERGE_WITH_DEFAULTS указывает, что локально объявленные прослушиватели должны быть объединены с прослушивателями по умолчанию.

Теперь, когда мы запускаем описанный выше тест, прослушиватель будет регистрировать каждое событие, которое он получает:

[main] INFO  o.s.t.c.s.DefaultTestContextBootstrapper - Using TestExecutionListeners: 
[[email protected]38364841, 
org.springframewor[email protected]28c4711c]
[main] INFO  c.b.t.CustomTestExecutionListener - beforeTestClass : 
class com.baeldung.testexecutionlisteners.TestExecutionListenersWithoutMergeModeUnitTest
[main] INFO  c.b.t.CustomTestExecutionListener - prepareTestInstance : 
class com.baeldung.testexecutionlisteners.TestExecutionListenersWithoutMergeModeUnitTest
[main] INFO  o.s.c.s.GenericApplicationContext - 
Refreshing [email protected]68ef40: startup date [XXX]; 
root of context hierarchy
[main] INFO  c.b.t.CustomTestExecutionListener - beforeTestMethod : 
public void com.baeldung.testexecutionlisteners.TestExecutionListenersWithoutMergeModeUnitTest
.whenValidNumbersPassed_thenReturnSum()
[main] INFO  c.b.t.CustomTestExecutionListener - afterTestMethod : 
public void com.baeldung.testexecutionlisteners.TestExecutionListenersWithoutMergeModeUnitTest
.whenValidNumbersPassed_thenReturnSum()
[main] INFO  c.b.t.CustomTestExecutionListener - afterTestClass : 
class com.baeldung.testexecutionlisteners.TestExecutionListenersWithoutMergeModeUnitTest

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

Использование @TestExecutionListener для регистрации слушателей подходит, если оно используется в ограниченном количестве тестовых классов. Но, это может стать громоздким, чтобы добавить его ко всему набору тестов.

Мы можем решить эту проблему, воспользовавшись поддержкой, предоставляемой механизмом SpringFactoriesLoader для автоматического обнаружения реализаций TestExecutionListener .

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

org.springframework.test.context.TestExecutionListener=\
com.baeldung.testexecutionlisteners.CustomTestExecutionListener

4.3. Упорядочение реализаций TestExecutionListener по умолчанию

Когда Spring обнаружит реализации по умолчанию TestExecutionListener через механизм SpringFactoriesLoader , он отсортирует их с помощью AnnotationAwareOrderComparator Spring. Это делает честь интерфейсу Spring Ordered и аннотации |/@Order для заказа.

Обратите внимание, что все реализации по умолчанию TestExecutionListener , предоставляемые Spring implement , упорядочены с соответствующими значениями. Поэтому мы должны убедиться, что наша пользовательская реализация TestExecutionListener зарегистрирована в правильном порядке. Следовательно, мы реализовали Ordered в нашем пользовательском прослушивателе:

public class CustomTestExecutionListener implements TestExecutionListener, Ordered {
    // ...
    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    };
}

Но мы можем использовать аннотацию @Order вместо .

5. Заключение

В этой статье мы рассмотрели, как реализовать пользовательский TestExecutionListener . Мы также рассмотрели прослушиватели по умолчанию, предоставляемые Spring framework.

И, конечно же, код, сопровождающий эту статью, доступен на GitHub.