Springのapplication.propertiesを環境毎に分ける
Springのapplication.propertiesはローカル開発環境用、単体テスト用、ステージング環境用、本番環境用などに分ける必要がある。
簡単な分け方として、環境によらず常に同じ値にするものはapplication.propertiesに設定して環境毎に変わるもの(あるいは特定の環境だけ設定値を上書き変更したいもの)はapplication-local.properties, application-production.propertiesなどに設定するとする。application.propertiesにはspring.profiles.active=local
を設定して、JavaVMシステムプロパティ(-Dspring.profiles.active
)や環境変数(SPRING_PROFILES_ACTIVE
)を設定しない限りデフォルトでローカル開発環境で動かすとする。
application.properties
spring.profiles.active=local
common_setting_a=value1
common_setting_b=value2
application-local.properties
env_varing_setting_c=value3
env_varing_setting_d=value4
※もっともおすすめの方法として、後にこの書き方を少し変更するため注意
IntelliJ IDEAからアプリを実行する
mainメソッドの実行ボタンをクリックして「Modify Run Configuration」を開き、VM optionsかEnvironment variablesに特定の環境を設定すれば、その環境に対応したプロパティファイルが読み込まれる。
ただ、spring.profiles.active
を設定しているので、IntelliJ IDEAからローカルで開発を行う分には「Modify Run Configuration」で設定する必要がない。
IntelliJ IDEAからJUnitを実行する
IntelliJ IDEAからテスト環境に対応したプロパティファイルを読み込んだ上でJUnitを実行する方法を考える。
コマンドラインから実行する場合はJavaVMシステムプロパティをオプションとして渡せば問題なく実行できるが、IntelliJ IDEAの実行ボタンから実行する場合に、どのようにJavaVMシステムプロパティを渡せばよいかが一見してわからない。
application-test.propertiesとspring.profiles.active
一つ目の方法は、まずapplication-test.propertiesを用意する。
mainメソッドの「Modify Run Configuration」と同様にJUnitの「Modify Run Configuration」のVM optionsかEnvironment variablesでapplication-test.propertiesを読み込むようにすることができる。
しかし、JUnitの各テストクラス及び各テストメソッドごとにConfigurationがあるため、全部に設定することは現実的ではない(統一的に設定する方法は見つけられず、また存在しないはず)。
対応策として、application.propertiesのspring.profiles.active
をtest
に設定し、通常のローカル開発でもVM optionsかEnvironment variablesを設定するというのがある。アプリ起動のConfigurationは一箇所なのに対してJUnitのConfigurationがテスト毎のため、JUnitのプロパティをデフォルトにしてしまうということだ。
デメリット
この方法のデメリットは、デフォルトがローカル環境ではなくテスト環境というのが直感的ではないという点。
application.propertiesをtest/resourcesにおく
二つ目の方法は、テスト専用のapplication.propertiesをtest/resourcesに置く。
JUnit実行時にはtest/resources/application.propertiesが優先して読み込まれるため、「Modify Run Configuration」のVM optionsかEnvironment variablesの設定は必要ない。
デメリット
この方法のデメリットは、プロダクションコードの方は共通設定をapplication.propertiesに書き、環境毎の設定をapplication-local.properties等に書くというように分離していたのを、JUnitのapplication.propertiesは全て一ファイルに書かなければいけない点。
spring.profiles.groupを使ってデメリットを解消する
spring.profiles.group
を使ってデメリットを解消でき、もっともおすすめできる構成となる。
spring.profiles.group
簡単な分け方として、環境によらず常に同じ値にするものはapplication.propertiesに設定して環境毎に変わる値にするもの(あるいは特定の環境だけ設定値を上書き変更したいもの)はapplication-local.properties, application-production.propertiesなどに設定していた。
これをspring.profiles.group
を使ってもう少し整理する。
application.propertiesは、デフォルトでアクティブにしたいものを決めるためにspring.profiles.active
がある点は変わらないが、その他の共通設定はapplication-common.propertiesに移設する。application-common.propertiesはspring.profiles.group
を使ってどの環境でも読み込むようにする。
application.properties
spring.profiles.active=local-group
spring.profiles.group.local-group=common,local
spring.profiles.group.production-group=common,production
application-common.properties
common_setting_a=value1
common_setting_b=value2
application-local.properties
env_varing_setting_c=value3
env_varing_setting_d=value4
test/resources/application.propertiesからmain/resources/application-common.propertiesを読み込む
test/resources/application.propertiesからmain/resources/application-common.propertiesを読み込むことができる。test/resources/application.propertiesではapplication-common.propertiesとテスト専用設定ファイルを読み込むようにtest-group
を定義して、spring.profiles.active
をtest-group
に設定する。
test/resources/application.properties
spring.profiles.active=test-group
spring.profiles.group.test-group=common,test
test/resources/application-test.properties
env_varing_setting_c=testValue3
env_varing_setting_d=testValue4
ちなみにapplication-test.propertiesはtest/resourcesではなくmain/resourcesに配置してもいい(application-common.propertiesをtest/resources/application.propertiesが読み込めるのと同様に、main/resources/application-test.propertiesも読み込めるため)。
application-local.propetiesとapplication-test.propertiesの構造はほぼ同じになるだろうから、同じディレクトリにおいたほうがいいかもしれない。
main/resources/application-test.properties
env_varing_setting_c=testValue3
env_varing_setting_d=testValue4
Gradleのtest
メソッドでjvmArgs
を設定する
Gradleのtest
メソッド内で強制的にjvmArgs += ['-Dspring.profiles.active=test']
とする方法もある。
問題なく動くが、力技なのであまり勧めない。
まとめ
共通設定部分を記載するapplication-common.propertiesを用意するとspring.profiles.group
を定義する必要もでるため、プロパティファイルの読み方が若干難しくなる。しかし、設定ファイルの整理整頓具合を考えると、spring.profiles.group
を導入してtest/resources/application.propertiesに以下のみを記載する方法がベストではないかと考える。
spring.profiles.active=test-group
spring.profiles.group.test-group=common,test
環境
- Java 17
- Spring Boot 2.6.2
- IntelliJ IDEA 2021.2.3 (Community Edition)