CoroutinesのUnit Testメモ

追記: この記事は古くなってますので、以下のドキュメントを参考にしてください。

まだよく分かってないこと多いですが、試したことをメモしておきます。

Android Studioでの実行を想定しています。また、AssertionはTruthを使ってます。

単純なsuspend関数

テスト対象

テストコード

単純なsuspend関数はテストメソッドを runBlocking で囲むだけで大丈夫です。

withContext

テスト対象

テストコード

suspend関数内でwithContextでDispatcherを切り替えてるものも、同様に runBlocking で囲むだけです。

注意として Dispatchers.Main だけはエラーになります。次で対応方法を見せます。

Dispatchers.Main

テスト対象。先程のは IO を使ってましたが、今回は Main を使ってます。

テストコード

Dispatchers.Main を使った場合はそのままテストを実行すると以下のようなエラーメッセージが表示されます。

java.lang.IllegalStateException: Module with the Main dispatcher had failed to initialize. For tests Dispatchers.setMain from kotlinx-coroutines-test module can be used

Dispatchers.Main が初期化できないため、エラーになっています。エラーメッセージに対応方法が書いてあるので、それをやります。

kotlinx-coroutines-test

kotlinx-coroutines-test を使います。

build.gradleに以下を追加します。

testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.1.0'

Dispatchers.setMain を使って Dispatchers.Main を別のDispatcherに置き換えます。

これでテストが通ります。

ちょっと分かってないこととしては、setMainに渡すDispatcherを Dispatchers.Default にするとうまくテストが通らないことがありました。 Dispatchers.Unconfined だとうまくいくのですが、呼び出し元のスレッドで実行されるからってことですかねぇ(自信ない)

まとめ

runBlocking を使えばだいたい大丈夫な気がします。何かまた気づいたら書きます。

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store