これは はてなエンジニア Advent Calendar 2019 13日目の記事です。
Kotlin Coroutinesのコルーチンをテストする時に必要なテクニックを紹介します。
コルーチンを同期的に実行したい
コルーチンを使って非同期処理をしているが、テストをする時には同期的に実行してほしいことはよくありますよね。
TestCoroutineScope
と TestCoroutineDispatcher
を使えば簡単にできます。
また、 runBlockingTest
を使えばこれらのクラスが自動的に使われます。
CoroutineDispatcherを置き換える
普段使っているCoroutineDispatcherをテスト時に TestCoroutineDispatcher
に置き換えるには下記のような方法があります
Dispatchers.Main
kotlinx-coroutines-test
に含まれている Dispatchers.setMain
/ Dispatchers.resetMain
を使いましょう
@Before fun setUp() { Dispatchers.setMain(TestCoroutineDispatcher()) } @After fun tearDown() { DIspatchers.resetMain() }
Dispatchers.Default / Dispatchers.IO 他
直接置き換える手段はないので、DIしましょう。
Flowに流れる値をテストする
Flow.collect
をコルーチン内で実行すると値を全部受け取るまで処理がそこで止まります。
例えばRoomが返すような終わりのないFlowはキャンセルしない限り collect
から先に進めないので、 launch
で新しいコルーチンを立ち上げるとよいです。
その時 TestCoroutineScope
や runBlockingTest
を一緒に使ってやると Flow.collect
が同期的に実行されます
@Test fun test() = runBlockingTest { val flow = // create flow var actual = null val flowCollectJob = launch { flow.collect { actual = it } } // ここでFlowに値が流れそうなことを何かする // yield()でこのコルーチンがDispatcherを一旦手放すことでflow.collectに渡したblockが実行され値が反映される assertThat(actual).isEqualTo(expected) // 最後にキャンセルしてやらないと完了していないコルーチンがあるので例外が起きる flowCollectJob.cancel() }
宣伝
2020年2月に五反田で開催されるDroidKaigi 2020でKotlin Coroutinesについて発表します。Kotlin Coroutinesの使い方に困ってる方は是非見に来てください!
これから始めるKotlin Coroutinesの導入 Kotlin Coroutinesが正式リリースされて1年が過ぎ、もはや私たちのAndroidアプリ開発には欠かせないものとなりました。 コルーチンはRxJavaのようなストリームやコールバック方式と比べて非同期的な処理を直感的に記述でき、これまでRxJavaを使っていたようなユースケースをある程度置き換えられるようになっています。 私はこの1年と少しでKotlin Coroutinesを複数のアプリに導入し既存のパラダイムの置き換えを進めてきました。 Kotlin Coroutinesの導入を行ったことでAndroidアプリ開発が楽になりましたが、大変になったこともありました。 恐らくKotlin Coroutinesが難しく感じて導入をためらっている方もいるでしょう。 このセッションでは、既存のAndroidアプリにKotlin Coroutinesを導入したことによってAndroidアプリ開発がどう変わったか、 Kotlin Coroutinesの導入を行ったことで困ったことをどう解決したかなどを紹介します。 皆様のKotlin Coroutinesの導入の参考になれば幸いです。 - RxJavaを使って書かれたコードを置き換える - RxJavaを使った世界観にKotlin Coroutinesを混ぜる - Retrofitを用いたHTTP通信をKotlin Coroutinesに対応 - RoomをKotlin Coroutinesで利用する - Kotlin CoroutinesとView層との組み合わせ - Kotlin CoroutinesとLiveDataの使い分け - Kotlin CoroutinesをViewModelで活用する - Kotlin Coroutinesとテスト - 例外処理 - キャンセル可能に作る
明日の担当は id:polamjag です。