Springアプリケーションイベントの単体テスト は何をしますか?
Springアプリケーションイベントの単体テストパターンを提供します。ApplicationEventPublisherを使用したイベント発行の検証、@EventListenerアノテーションの動作確認、非同期イベント処理のテストを行います。イベントリスナーのテスト、アプリケーションイベントのモック、Spring Bootサービスでのイベント発行検証に役立ちます。
概要
このスキルは、Spring Frameworkのイベント機構を利用したアプリケーションのテストを支援します。主要な機能は以下の通りです。
- イベント発行の検証:
ApplicationEventPublisherを介して特定のイベントが正しく発行されたかを確認します。 @EventListenerのテスト: アノテーションベースのイベントリスナーが期待通りに動作するかを検証します。- 非同期イベントのテスト:
@Asyncアノテーションと組み合わせた非同期イベント処理を適切にテストします。 - モッキング:
Mockitoを使用したApplicationEventPublisherのモック作成を支援します。
前提条件
- Java 17 以上
- Spring Boot 3.x
- JUnit 5
- Mockito (テスト用)
セットアップ
Maven
<!-- Spring Boot Starter Test (JUnit 5, Mockito を含む) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Gradle
testImplementation 'org.springframework.boot:spring-boot-starter-test'
使用方法
1. イベント発行の検証 (ApplicationEventPublisher のモック)
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationEventPublisher;
public class OrderServiceTest {
@Test
void shouldPublishOrderCreatedEvent() {
// Arrange
ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
OrderService orderService = new OrderService(publisher);
// Act
orderService.createOrder(new Order("123"));
// Assert
verify(publisher).publishEvent(any(OrderCreatedEvent.class));
}
}
2. @EventListener のテスト
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationEventPublisher;
@SpringBootTest
class OrderEventListenerTest {
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
private OrderEventListener listener;
@Test
void shouldHandleOrderCreatedEvent() {
// Arrange
OrderCreatedEvent event = new OrderCreatedEvent("123");
// Act
publisher.publishEvent(event);
// Assert
// リスナーがイベントを処理したことを確認 (例: フラグや状態の確認)
assertTrue(listener.isEventHandled());
}
}
3. 非同期イベントのテスト
非同期イベントをテストする際は、@EnableAsync を有効にし、テストクラスに @SpringBootTest を付与します。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootTest
@EnableAsync
class AsyncEventListenerTest {
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
private AsyncEventListener listener;
@Test
void shouldHandleEventAsynchronously() throws InterruptedException {
// Arrange
SomeEvent event = new SomeEvent("data");
// Act
publisher.publishEvent(event);
// Assert
// 非同期処理の完了を待つ (例: CountDownLatch を使用)
assertTrue(listener.getLatch().await(5, TimeUnit.SECONDS));
}
}
ベストプラクティス
- 単一責任: 各テストは1つのイベント発行またはリスナー動作に焦点を当ててください。
- モックの使用:
ApplicationEventPublisherはモックし、実際のイベントリスナーは統合テストで検証します。 - 非同期テストの同期: 非同期イベントをテストする場合は、
CountDownLatchやAwaitilityライブラリを使用して、処理完了を確実に待つようにします。 - イベントの構造: イベントクラスは
java.util.EventObjectを継承するか、シンプルなPOJOとして実装するとテストが容易です。
トラブルシューティング
- イベントが処理されない:
@EventListenerのメソッドがpublicであること、および Spring 管理の Bean に定義されていることを確認してください。 - 非同期イベントが同期的に実行される:
@EnableAsyncアノテーションがテストコンテキストで有効になっているか確認します。また、TaskExecutorの適切な設定が必要です。 - Mockito の verify が失敗する:
ApplicationEventPublisherが正しく注入されていること、およびモックがテストメソッドごとにリセットされていることを確認します。