1. Введение
Одна из доступных аннотаций в Spring Framework — @Scheduled
. Мы можем использовать эту аннотацию для выполнения задач по расписанию .
В этом руководстве мы рассмотрим, как протестировать аннотацию @Scheduled
.
2. Зависимости
Во-первых, давайте начнем создавать приложение Spring Boot на основе Maven из Spring Initializer :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/>
</parent>
Нам также понадобится несколько стартеров Spring Boot:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
И давайте добавим зависимость для JUnit 5 в наш pom.xml
:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
Мы можем найти последнюю версию Spring Boot на Maven Central .
Кроме того, чтобы использовать Awaitility в наших тестах, нам нужно добавить его зависимость:
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>3.1.6</version>
<scope>test</scope>
</dependency>
3. Простой пример @Scheduled
Начнем с создания простого класса Counter :
@Component
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
@Scheduled(fixedDelay = 5)
public void scheduled() {
this.count.incrementAndGet();
}
public int getInvocationCount() {
return this.count.get();
}
}
Мы будем использовать запланированный
метод, чтобы увеличить количество
. Обратите внимание, что мы также добавили аннотацию @Scheduled
для выполнения за фиксированный период в пять миллисекунд.
Кроме того, давайте создадим класс ScheduledConfig
для включения запланированных задач с помощью аннотации @EnableScheduling
:
@Configuration
@EnableScheduling
@ComponentScan("com.foreach.scheduled")
public class ScheduledConfig {
}
4. Использование интеграционного тестирования
Одной из альтернатив для тестирования нашего класса является использование интеграционного тестирования . Для этого нам нужно использовать аннотацию @SpringJUnitConfig
, чтобы запустить контекст приложения и наши bean-компоненты в тестовой среде:
@SpringJUnitConfig(ScheduledConfig.class)
public class ScheduledIntegrationTest {
@Autowired
Counter counter;
@Test
public void givenSleepBy100ms_whenGetInvocationCount_thenIsGreaterThanZero()
throws InterruptedException {
Thread.sleep(100L);
assertThat(counter.getInvocationCount()).isGreaterThan(0);
}
}
В этом случае мы запускаем наш компонент Counter
и ждем 100 миллисекунд, чтобы проверить количество вызовов.
5. Использование ожидания
Другой подход к тестированию запланированных задач — использование Awaitility . Мы можем использовать Awaitility DSL, чтобы сделать наш тест более декларативным:
@SpringJUnitConfig(ScheduledConfig.class)
public class ScheduledAwaitilityIntegrationTest {
@SpyBean
private Counter counter;
@Test
public void whenWaitOneSecond_thenScheduledIsCalledAtLeastTenTimes() {
await()
.atMost(Duration.ONE_SECOND)
.untilAsserted(() -> verify(counter, atLeast(10)).scheduled());
}
}
В этом случае мы внедряем в наш bean- компонент аннотацию @SpyBean
, чтобы проверить, сколько раз запланированный
метод вызывается в течение одной секунды.
6. Заключение
В этом руководстве мы показали некоторые подходы к тестированию запланированных задач с использованием интеграционного тестирования и библиотеки Awaitility.
Нужно учитывать, что хотя интеграционные тесты и хороши, в целом лучше сосредоточиться на модульном тестировании логики внутри запланированного метода .
Как обычно, все примеры кода, показанные в этом руководстве, доступны на GitHub .