🧪

recordで@ConfigurationPropertiesを使った場合のテストの書き方

2024/03/23に公開

はじめに

recordクラスを@ConfigurationPropertiesアノテーションを付与して実装を進めている場合のテストの書き方を紹介しようと思います。
知らずにテスト実装をしようとすると、値が取れなくて結構調べるのに時間がかかったので😅
同じような実装をしている方はぜひこの記事を読んでいただければと思います!
前の記事を読んでいただくとスムーズに実装して頂けるかと思います。

TL;DR

下記アノテーションをクラスレベルに付与する。

@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(${recordクラス}.class)
@TestPropertySource("classpath:${プロパティファイル名}")
public class SampleTest {
}

開発環境

  • PC
    • MacBook Pro
    • macOS(Sonoma)
  • Other
    • JDK Version
      • 17.0.6
    • Spring Boot Version
      • 3.0.2
      • Lombokとspring-boot-starter-testを使ってます

実装方法

前提実装

  • こちらの記事参考にrecordクラスを作成し、@EnableConfigurationPropertiesアノテーションなど設定済みの状態

テストコード(serviceクラス)

今回使用するのは、下記のようなserviceクラス

SampleService.java
@Service
@RequiredArgsConstructor
public class SampleService {

 // 作成したrecordクラス
 private final SampleConfigProperties sample;

 private String sampleMethod() {
  return sample.hoge();
 }
}

プロパティファイル

secrets.properties
sample.hoge=hogehoge
DB_USER=root
DB_PASSWORD=password

テストコード(テストクラス)

SampleTest.java
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(SampleConfigProperties.class)
@TestPropertySource("classpath:secrets.properties")
public class SampleTest {

 @SpyBean
 private SampleService target;

 @SpyBean
 private SampleConfigProperties spySample;
}
  • @ExtendWith(SpringExtension.class)
    • こちらの@ExtendWith(SpringExtension.class) vs @ExtendWith(MockitoExtension.class)を見てもらうと@SpyBeanを使ってる理由もわかると思います[1]
  • @EnableConfigurationProperties(SampleConfigProperties.class)
    • @ConfigurationPropertiesがついたrecordクラス(Bean)のサポートを有効にするためつける[2]
  • @TestPropertySource("classpath:secrets.properties")
    • クラスパスのルートにある secrets.properties からプロパティを取得[3]

@Valueで書いた場合の実装方法との違い

  • org.springframework.test.util.ReflectionTestUtilsでmock化する必要がある
    • 詳しい記事はこちらをご参照ください!

https://qiita.com/DriftwoodJP/items/d8c8d544ab8da89630d8

  • 筆者のあくまで個人的な感想は下記になります。皆さんの意見を教えてください🙇‍♂️
    • プロパティファイルの値を使う場合、常に同じ値のケースがほとんどだと思っている
      • 複数存在しうる場合はenumとかを使う方がいいのでは?
    • テストファイルごとにReflectionTestUtils.setField()で値をセットしなきゃいけないのが面倒
    • プロパティ名の変更だったり、プロパティに対する値を変更する場合、テストケースの修正も合わせて面倒くさそう

最後に

recordクラスを使ってプロパティファイルの値を読み込むのは良かったものの、テストでその値を取って来れずに結構悩みました。。
でもそのおかげでApplicationContextについてだったり、@ConfigurationPropertiesアノテーションの使い方の知識がより深まったかなと思います。
結果的に開発手法やルールに応じて、@Valueだったり今回のようなrecordを使った実装を出来るようになったのが一番の成果かなと思いました🙌
記事を読んだ感想や皆さんの意見をコメントして頂けると、大変嬉しいです!

他の参考文献

  • 【Spring-Boot】Junitを利用した単体テストでよく利用するアノテーション

https://qiita.com/Kohei-Kato/items/02a6faecfb3248023c96


脚注
  1. @ExtendWith(SpringExtension.class)@ExtendWith(MockitoExtension.class)の違いについて ↩︎

  2. @EnableConfigurationPropertiesのドキュメント ↩︎

  3. @TestPropertySourceのドキュメント ↩︎

GitHubで編集を提案

Discussion