Android のコンポーネント(Activity)の単体テスト3 - 別アクティビティからの結果を取得する
タイトル長いな……。簡潔に言うと onActivityResult
のテストをする方法です。
前回の続きになります。
pickles-ochazuke.hatenablog.com
概要
前回と同じ Espresso.Intents
を使います。Espresso-Intents については、前回話しているので飛ばします。
onActivityResult
は、requestCode, resultCode, インテントデータを受け取ります。この内、resultCode と インテントデータの2つのデータは、別のアクティビティが setResult()
で設定しています。この別のアクティビティが設定する部分をスタブ化します(スタブ化は、簡単に言えば、機能を真似するようにする。ということです)。
スタブ化するためには、Intents.intending()
とその戻り値である OngoingStubbing
のメソッド respondWith()
を使います。
次のように使います。
intending(hasComponent(OtherActivity::class.java.name)).respondWith(result)
使い方としては、intending()
の引数にスタブ化したい対象が一致する条件を渡し、そのスタブ化の対象が呼ばれたときに渡したい結果を respondWith()
に渡します。
上記だと OtherActivity
が呼ばれた(OtherActivity が作成された)ときに、そのアクティビティが終了されたものとし、result を onActivityResult() の各引数(resultCode, intent)に渡されます。
上手く説明出来ませんが、実際に使用すると感覚が掴めると思います。
実践では、前回のプロジェクトを使うので、なければこちらの ActivityUnitTestExample_2
ブランチを使うと同じ状態に出来ます。
実践
今回追加する処理は、前回のプロジェクトを使い、OtherActivity
を起動したら挨拶の情報を持ったインテントが返ってくるので、それをテキストに反映させるという処理にします。テストで確認するだけなので OtherActivity
側は何も変更しません。ですので、実際のアプリで OtherActivity
は何も返してきません。
まずは、別アクティビティから結果を受け取れるようにします。MainActivity.kt
を以下のように変更します。
import android.widget.TextView ... override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode != RESULT_OK) { return } if (requestCode != 1) { return } findViewById<TextView>(R.id.helloWorld).text = data?.getStringExtra("greeting") }
ついでに、startActivity()
から startActivityForResult()
に変更します。
startActivityForResult(intent, 1)
次にテストを追加します。
import android.app.Activity import android.app.Instrumentation import android.content.Intent import androidx.test.espresso.intent.Intents.intending @Test fun OtherActivityから受け取った結果がテキストに反映されるべき() { val intent = Intent().apply { this.putExtra("greeting", "Hi World!") } val result = Instrumentation.ActivityResult(Activity.RESULT_OK, intent) intending(hasComponent(OtherActivity::class.java.name)).respondWith(result) onView(withId(R.id.button)).perform(click()) onView(withId(R.id.helloWorld)).check(matches(withText("Hi World!"))) }
intending()
手前までは、ActivityResult
を作成しています。intending()
の引数は、スタブ化したい対象の条件を指定しています。そして、respondWith()
に ActivityResult
を渡しています。
https://developer.android.com/reference/android/app/Instrumentation.ActivityResult
スタブ化が完了したら、Espresso で UI を操作し、ビューが期待通りになっているか検証します。デバッグ実行を行い、onStartActivity()
と onView(withId(R.id.button)).perform(click())
にブレークポイントを設定するとが perform()
実行されたあとに onStartActivity()
で止まることが確認できます。
以上です。
ここまで行った状態が途中に上げた Github にあるリポジトリの ActivityUnitTestExample_3
ブランチです。
雑記
GW で調べていたことを放出しました。本当は Todo アプリを作って Android の理解を深めようと思ったのですが、その Todo アプリをテストしようとしたらいろいろエラーを踏んで3,4日潰れました……。まだテストのことは理解が足りていないので間違ったことを書いているかもしれませんが、誰かの助けになれば幸いです(間違っていれば指摘しただけると助かります)。
今年のGWは、技術書読み進めたり、Android のテスト調べたり、これ書いたりと割と充実していました(それでもやり残したことはありますが)。テストのエラー解決できないとき諦めようと思いましたが時間あけて考え直すと解決したので、やっぱり諦めずにいるのは大事だなと思いました(そして適度な休息!)。
あと恋する小惑星を見て地学に興味湧いたので NHK の地学基礎って動画見てるんですがかなり面白くてノートにまとめたりしています。