条件によってはテストを実行しないアノテーション、JUnit5
のDisabledIf
だけでなく、Spring
のDisabledIf
もあります。
基本的にはJUnit5
のDisabledIf
シリーズで十分なことが多いのですが、Spring
側で用意されているものも素振りします。
環境
- Java
- 17
- SpringBootTest
- 2.7.4
前提
設定ファイルの準備
Spring
のDisabledIf
を使用する最大のメリットは、設定ファイルによって挙動を変更できるところです。そのため、application.yml
を定義します。
app: config: appName: "Kirimaru" local: "true"
テストクラスのセットアップ
テストで設定ファイルを読み込めるようにします。
// 設定ファイルを読み込むアノテーションとinitializers @SpringJUnitConfig(initializers = ConfigDataApplicationContextInitializer.class)
他にも設定ファイルを読み込めるのであればSpringBootTest
等々のアノテーションでも問題ありません。ただ、ユニットテストレベルでは不要なDI等々も行ってしまうので、SpringJUnitConfig
のほうが早く起動できます。
@SpringBootTest
対応
Spring
機能を使用したいので、loadContext
はtrue
を設定します。
${path}
${path}
を使用すると、設定ファイルの値を読み込めます。なお、読み込んだ値がtrue
かfalse
である必要があります。先ほどapp.config.local
にtrue
を設定しているので、次のテストは動かないように制御できます。
@DisabledIf(value = "${app.config.local}", loadContext = true) @Test void test_01() { fail(); }
#{expression}
#{expression}
を使用すると、中に条件式を記載できます。Spring
で設定ファイルを読み込むクラスはEnvironment
クラスです。Environment
クラスを利用して、app.config.appName
の値がkirimaru
のときに、テストが動かないように制御するには次の式を使用します。
@DisabledIf( value = "#{environment.getProperty('app.config.appName').equalsIgnoreCase('kirimaru')}", loadContext = true ) @Test void test_02() { fail(); }
なお、#{}
内部で${}
は使用できないようです。できるのかもしれませんが、私には理解できませんでした。似たような書き方を聞いている掲示板はあるのですが、解決にはいたっていないようです。
ログを見る限り、app.config.appName
のKirimaru
は読み込めているのですが、Kirimaru
を元にBean名を探しているようでした。
@DisabledIf(value = "#{${app.config.appName}.equalsIgnoreCase('kirimaru')}", loadContext = true)
org.junit.jupiter.engine.execution.ConditionEvaluationException: Failed to evaluate condition [org.springframework.test.context.junit.jupiter.DisabledIfCondition]: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'Kirimaru' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
備考
JUnit5
のDisabledIf
シリーズも調べるとおもしろいので、ぜひ興味があるときに調べてみてください。
org.junit.jupiter.api
の5.8.2には次のシリーズがありました。
- DisabledIf
- DisabledIfEnvironmentVariable
- DisabledIfSystemProperty
- DisabledOnJre
- DisabledOnOs
- DisabledForJreRange
- および、上記とは逆のEnabledIfシリーズ
適切ではないですがローカルで動いてCI上で落ちるテストがある場合は、@DisabledOnOs(OS.LINUX)
のように回避することもあります。
ソースコード
終わりに
Spring
のDisabledIf
が便利に使えそうだったのですが、検証に時間がかかってしまいました。loadContext
をtrue
にする必要があったり、SpEL式
がうまく書けなかったり。
これを覚えたことで今後回避したいアノテーションを作るときには、ちょっとした作り込みをする必要がなくなったので、未来の工数を大きく削減できました。
特定の環境では動かしたくないテストは大量にあるので、今後も活用していきたいです。
参考情報
- https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/test/context/junit/jupiter/DisabledIf.html
- https://oohira.github.io/junit5-doc-jp/user-guide/#writing-tests-disabling