Robolectric 4.4 がリリース
2020年8月末にv4.4がリリースされたようです。リリースノート
v4.4では大きな変更があり、バージョンアップしたらテストの大半が失敗するなんてこともあります。
この記事では、v4.4での変更点と、テストが失敗する時の対処方法をまとめていきます。
Robolectric 4.4 の大きな変更点
リリースノートにある通り、PAUSED looper modeがデフォルトになったことが大きな変更点です。
これによって、大半のテストが失敗するようになるかも知れません。
PAUSED looper mode の説明は、公式のドキュメントに詳しく書いています。
PAUSED looper mode の説明
公式ドキュメントを要約すると、以下のようなことが書いています。
-
PAUSED looper modeでは、メインルーパーのキューにあるタスクは明示的に実行する必要がある。 - メインルーパーのキューに未実行のタスクがあってテストが失敗した場合は、エラーメッセージを表示してくれる。
エラーメッセージが出た時の対処方法
メインルーパーのキューに未実行のタスクがあってテストが失敗した場合は、次のようなエラーメッセージを表示されます。
Main looper has queued unexecuted runnables.
This might be the cause of the test failure. You might need a shadowOf(getMainLooper()).idle() call.
このエラーメッセージを解決する方法は2つあります。
- エラーメッセージに従って、適切なタイミングで
shadowOf(getMainLooper()).idle()を実行する。 - テストクラスに
@LooperMode(LooperMode.Mode.LEGACY)をつけて、v4.4以前と同じモードでテストする。
適切なタイミングでshadowOf(getMainLooper()).idle() を実行する
適切なタイミングと言っても、テストコードによってそのタイミングはバラバラです。
基本的にはassertThat(...)やverify(...)など、テストの結果を出す直前に実行するといいと思います。
テストクラスに@LooperMode(LooperMode.Mode.LEGACY) をつけて、v4.4以前と同じモードでテストする
shadowOf(getMainLooper()).idle()を実行するタイミングがよくわからず、調査に時間がかかりそうな場合は、この方法で一時的に回避するのも一つの方法だと思います。
調査が必要なところ
Robolectric 4.3.1 以降では、Android API 29 でテストする時に次のようなメッセージが表示されます。
[Robolectric] WARN: Android SDK 29 requires Java 9 (have Java 8).
Tests won't be run on SDK 29 unless explicitly requested.
つまりは、Android API 29でテストするにはJava 9が必要になるそうです。
Robolecric 4.3.1のリリースノート
ですが、AndroidStudioに組み込まれているJDKは1.8なので、Java8で実行している場合が多いと思います。
その時に、Android SDK 28でテストが動くのか、Android SDK 29で動くのかはっきりわかりませんでした。