Takuji->find;

株式会社はてなでアプリケーションエンジニアやってます、技術的な記事を書いているつもり

Kotlin Coroutinesをテストする

これは はてなエンジニア Advent Calendar 2019 13日目の記事です。

Kotlin Coroutinesのコルーチンをテストする時に必要なテクニックを紹介します。

コルーチンを同期的に実行したい

コルーチンを使って非同期処理をしているが、テストをする時には同期的に実行してほしいことはよくありますよね。

TestCoroutineScopeTestCoroutineDispatcher を使えば簡単にできます。

また、 runBlockingTest を使えばこれらのクラスが自動的に使われます。

kotlin.github.io

kotlin.github.io

CoroutineDispatcherを置き換える

普段使っているCoroutineDispatcherをテスト時に TestCoroutineDispatcher に置き換えるには下記のような方法があります

Dispatchers.Main

kotlinx-coroutines-test に含まれている Dispatchers.setMain / Dispatchers.resetMain を使いましょう

@Before
fun setUp() {
  Dispatchers.setMain(TestCoroutineDispatcher())
}

@After
fun tearDown() {
  DIspatchers.resetMain()
}

kotlin.github.io

kotlin.github.io

Dispatchers.Default / Dispatchers.IO 他

直接置き換える手段はないので、DIしましょう。

Flowに流れる値をテストする

Flow.collect をコルーチン内で実行すると値を全部受け取るまで処理がそこで止まります。

例えばRoomが返すような終わりのないFlowはキャンセルしない限り collect から先に進めないので、 launch で新しいコルーチンを立ち上げるとよいです。

その時 TestCoroutineScoperunBlockingTest を一緒に使ってやると 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とテスト
- 例外処理
- キャンセル可能に作る

droidkaigi.jp

明日の担当は id:polamjag です。