unit-test-scheduled-async は何をしますか?
Springの@Scheduledおよび@AsyncメソッドをJUnit 5、CompletableFuture、Awaitility、Mockitoを使って単体テストするためのパターンを提供します。タスクの実行とタイミングのモック化、実行回数の検証、cron式のテスト、リトライ動作の検証、スレッドプール動作のシミュレーションをカバーします。バックグラウンドタスク、cronジョブ、定期実行、スケジュールタスク、スレッドプール動作のテストに使用します。
対象プラットフォーム
- Spring Boot 3.0+
- JUnit 5
- Mockito
- Awaitility
- Java 17+
セットアップ
以下の依存関係をpom.xmlまたはbuild.gradleに追加してください。
Maven (pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
Gradle (build.gradle)
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.awaitility:awaitility'
主なテストパターン
1. @Scheduledメソッドのテスト
@SpringBootTest
class ScheduledTaskTest {
@Autowired
private ScheduledTask scheduledTask;
@MockBean
private SomeService someService;
@Test
void testScheduledExecution() {
// Awaitilityを使ってタスクの実行を待機
await().atMost(5, SECONDS).untilAsserted(() -> {
verify(someService, atLeast(1)).performAction();
});
}
}
2. @Asyncメソッドのテスト
@SpringBootTest
class AsyncTaskTest {
@Autowired
private AsyncTask asyncTask;
@Test
void testAsyncExecution() throws Exception {
CompletableFuture<String> future = asyncTask.processAsync("test");
String result = future.get(5, TimeUnit.SECONDS);
assertEquals("processed: test", result);
}
}
3. cron式のテスト
@Test
void testCronExpression() {
CronExpression cronExpression = CronExpression.parse("0 0/5 * * * ?");
assertNotNull(cronExpression);
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime next = cronExpression.next(now);
assertNotNull(next);
assertTrue(next.isAfter(now));
}
4. リトライ動作のテスト
@Test
void testRetryBehavior() {
when(someService.performAction())
.thenThrow(new RuntimeException("一時的なエラー"))
.thenThrow(new RuntimeException("一時的なエラー"))
.thenReturn("成功");
String result = retryService.executeWithRetry();
assertEquals("成功", result);
verify(someService, times(3)).performAction();
}
5. スレッドプール動作のテスト
@SpringBootTest
@TestPropertySource(properties = {
"spring.task.execution.pool.core-size=2",
"spring.task.execution.pool.max-size=4"
})
class ThreadPoolTest {
@Autowired
private TaskExecutor taskExecutor;
@Test
void testThreadPoolConfiguration() {
assertThat(taskExecutor).isInstanceOf(ThreadPoolTaskExecutor.class);
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) taskExecutor;
assertEquals(2, executor.getCorePoolSize());
assertEquals(4, executor.getMaxPoolSize());
}
}
ベストプラクティス
- Awaitilityを使用して非決定的なテストを避ける
CompletableFuture.get()のタイムアウトを常に設定する@MockBeanで依存関係をモック化する- cron式の検証には
CronExpressionクラスを使用する - スレッドプール設定はテストプロパティで上書きする