@Scheduledアノテーションをテストする方法

  • Spring

  • link:/category/testing/ [テスト]

1. 前書き

link:/spring-intro[Spring Framework]で利用可能な注釈の1つは_ @ Scheduled_です。 この注釈を使用して、https://www.baeldung.com/spring-scheduled-tasks [スケジュールされた方法でタスクを実行する]を使用できます。
このチュートリアルでは、_ @ Scheduled_アノテーションをテストする方法を探ります。

2.  依存関係

まず、https://start.spring.io/ [Spring Initializer]からlink:/spring-boot[Spring Boot] Mavenベースのアプリケーションの作成を開始しましょう。
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.2.RELEASE</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>
そして、link:/junit-5[JUnit 5]の依存関係を_pom.xml_に追加しましょう。
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
</dependency>
Spring Bootの最新バージョンは、https://search.maven.org/search?q = g:org.springframework.boot%20AND%20a:spring-boot-starter-parent [Maven Central]で見つけることができます。
さらに、テストでhttps://search.maven.org/search?q=g:org.awaitility%20AND%20a:awaitility[Awaitility]を使用するには、依存関係を追加する必要があります。
<dependency>
    <groupId>org.awaitility</groupId>
    <artifactId>awaitility</artifactId>
    <version>3.1.6</version>
    <scope>test</scope>
</dependency>

*3. 単純な_ @ Scheduled_ Sample *

簡単な_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_メソッドを使用して、_count_を増やします。 _ @ Scheduled_注釈も追加して、5ミリ秒の固定期間で実行することに注意してください。
また、_ScheduledConfig_クラスを作成して、_ @ EnableScheduling_アノテーションを使用してスケジュールされたタスクを有効にします。
@Configuration
@EnableScheduling
@ComponentScan("com.baeldung.scheduled")
public class ScheduledConfig {
}

4. 統合テストの使用

クラスをテストする代替手段の1つは、https://www.baeldung.com/integration-testing-in-spring [統合テスト]を使用することです。 そのためには、_ @ 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_ Beanを開始し、呼び出しカウントを確認するために100ミリ秒待機します。

*5.  使用wait

スケジュールされたタスクをテストする別のアプローチは、https://www.baeldung.com/awaitlity-testing [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に_https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/SpyBean.html [@SpyBean] _を注入します1秒間に_scheduled_メソッドが呼び出された回数をチェックするアノテーション。

6.  結論

このチュートリアルでは、統合テストとAwaitilityライブラリを使用して、スケジュールされたタスクをテストするためのいくつかのアプローチを示しました。
統合テストは優れていますが、一般的には、スケジュールされたメソッド内のロジックの単体テストに集中する方が良いことを考慮する必要があります*。
いつものように、このチュートリアルに示されているすべてのコードサンプルは、https://github.com/eugenp/tutorials/tree/master/testing-modules/spring-testing [GitHub]で入手できます。