1. 序章

Spring Framework で使用可能なアノテーションの1つは、@Scheduledです。 このアノテーションを使用して、スケジュールされた方法でタスクを実行することができます。

このチュートリアルでは、@Scheduledアノテーションをテストする方法について説明します。

2. 依存関係

まず、 SpringInitializerからSpring BootMavenベースのアプリケーションの作成を開始しましょう。

<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>

そして、 JUnit5の依存関係をpom.xmlに追加しましょう。

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
</dependency>

最新バージョンのSpringBootは、 MavenCentralにあります。

さらに、テストで 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 メソッドを使用して、countを増やします。 @Scheduled アノテーションも追加して、5ミリ秒の固定期間で実行することに注意してください。

また、 ScheduledConfig クラスを作成して、@EnableSchedulingアノテーションを使用してスケジュールされたタスクを有効にしましょう。

@Configuration
@EnableScheduling
@ComponentScan("com.baeldung.scheduled")
public class ScheduledConfig {
}

4. 統合テストの使用

クラスをテストするための代替手段の1つは、統合テストを使用することです。 これを行うには、 @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. 待機性の使用

スケジュールされたタスクをテストする別のアプローチは、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 アノテーションを挿入して、cheduledメソッドが1秒間に呼び出された回数を確認します。

6. 結論

このチュートリアルでは、統合テストとAwaitilityライブラリを使用してスケジュールされたタスクをテストするためのいくつかのアプローチを示しました。

統合テストは優れていますが、通常はスケジュールされたメソッド内のロジックの単体テストに焦点を当てた方がよいことを考慮する必要があります。

いつものように、このチュートリアルに示されているすべてのコードサンプルは、GitHubから入手できます。