TestConfigurationアノテーションとは
テスト用に追加の Bean またはカスタマイズを定義するために使用できる@Configuration。
(公式リファレンスより引用)
使用場面
アプリケーションの外部依存(例:外部API、データベースクライアントなど)を、テストコード実行時のみ本物の依存ではなく、テスト専用のインスタンスに置き換えたいとき。
実装例
テストコードを使用してテストを行う際にBean定義をテスト用に差し替える。
今回は例としてExternalClientクラス(独自クラス)をBean定義として登録する。
バージョン
- Java:25
- SpringBoot:3.5.7
ソースコード
AppConfig.java
// 本番用Config
@Configuration
public class AppConfig {
@Bean
ExternalClient client(){
return new Client("本番用外部クライアント");
}
}
AppTests.java
@SpringBootTest
class AppTests {
// テスト用Config
@TestConfiguration
static class AppTestConfig {
@Bean
@Primary
ExternalClient testClient(){
return new Client("テスト用外部クライアント");
}
}
@Test
void appTest() {
// テスト対象のメソッド呼び出し
// テスト対象メソッドの内部で@AutowiredでExternalClientのインスタンスを生成する想定
}
}
実装のポイント
同一のクラスのBean定義がテスト用と本番用の複数登録されるイメージ
- Bean定義が同名だと上書きしようとするため別名にする
- 同名だとBeanDefinitionOverrideExceptionが発生する
-
spring.main.allow-bean-definition-overriding=trueで上書きは可能になるが扱いには注意が必要
静的インナークラスとしてTestConfigurationを定義する
- インナークラスはアウタークラスに依存するためstaticでないとDIコンテナに読み込まれない
Bean定義に@Primaryをつける
-
@Configurationよりも@TestConfigurationが優先的にインジェクションされる - テスト以外の場合、
@TestConfigurationは無視されるため@Configurationがインジェクションされる
おまけ
テスト用Configを別クラスに切り分けることも可能。
(クラスのアクセス修飾子staticは不要となるためpubclicにする)
別クラスにする場合、テストクラスにインポートする必要がある。
AppTestConfig.java
@TestConfiguration
public class AppTestConfig {
@Bean
@Primary
ExternalClient testClient(){
return new Client("テスト用クライアント");
}
}
AppTests.java
@SpringBootTest
@Import(AppTestConfig.class)
class AppTests {
@Test
void appTest() {
// テスト対象のメソッド呼び出し
}
}
記事書くの初めてで苦戦しました。。。
(調べるの数時間+実際に記事に起こすの約3時間)