Android Unit Test


はじめに

Androidアプリ開発でUnit Test書いていますか?
僕はつい最近Unit Testを書き始めました。
その時に得た知見をまとめます。

  • Kotlin 1.3.31
  • Mockito-Kotlin 2.1.0
  • Assertj 3.11.1
  • Robolectric 4.2
app/build.gradle
// ...

dependencies {
    // ...

    // Mockito-Kotlin
    testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0'

    // Assertj
    testImplementation 'org.assertj:assertj-core:3.11.1'

    // Robolectric
    testImplementation 'org.robolectric:robolectric:4.2'

    // AndroidX
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
}

Unit Testの作成方法と実行

作成方法

  1. Android Studioでテストを作成したいクラスでCommand+Shift+T
  2. Create New Test...を押下
  3. 必要に応じて、テスト実行前に実行するメソッドsetUp/@Beforeとテスト実行後に実行するメソッドtearDown/@Afterにチェック

  4. テスト対象のメソッドにチェック(上記の画像)

  5. /app/src/testを選択
    (今回はUnit Testなので/app/src/testを選択しましたが、UI Testの場合は/app/src/androidTestを選択します)

実行

緑の再生ボタンを押すとclass単位 or メソッド単位でテストを実行できます。

Robolectricを用いたUnit Test

Androidのフレームワークに依存したコードのテストをする場合にRobolectricを用いてJVM上でシュミレートすることによりテストします。
実装例(クリップボードに文字列をコピーするメソッドのテスト)がこちらです。
この例ではAndroidXのInstrumentationRegistryを使ってcontextのインスタンスを作成しています。

UtilTest.kt
@RunWith(RobolectricTestRunner::class)
class UtilTest {

    @Test
    fun clipBoardCopy() {
        val context = InstrumentationRegistry.getInstrumentation().context
        Util.clipBoardCopy(context, "clip_test")
        val clipboardManager: ClipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
        val clipText = clipboardManager.text
        assertThat(clipText).isEqualTo("clip_test")
    }
}

また、Configアノテーションを使ってエミュレートするSDKのバージョンを指定できたりするので、詳しく知りたい方はRobolectricを見てください。

Assertjでアサーション

Assertjを使ってアサーションを書くと、メソッドチェーンで書けます。
文字列や数値など、いろんな種類のアサーションが用意されているので便利です。
実装例がこちらです。

assertThat("Kotlin")
    .isNotBlank()
    .contains("ot")
    .isEqualTo("Kotlin")

Mockito-Kotlinでモック作成

モックを使ってテストを書く際に、Mockitoというライブラリを使って書きました。
Kotlin仕様に拡張されているMockito-Kotlinを使います。
実装例がこちらです。

UtilTest.kt
@RunWith(RobolectricTestRunner::class)
class UtilTest {

    @Test
    fun isNetConnection() {
        val networkInfo: NetworkInfo = mock(name = "NetworkInfo")
        whenever(networkInfo.isConnected).thenReturn(true)

        val connectivityManager: ConnectivityManager = mock(name = "ConnectivityManager")
        whenever(connectivityManager.activeNetworkInfo).thenReturn(networkInfo)

        val context: Context = mock(name = "Context")
        whenever(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager)

        assertThat(Util.isNetConnection(context)).isTrue()
    }
}

最後に

今回はUnit Testに関する知見をまとめました。
CI/CDでのテスト実行までを目標としています。
今はUI Testを書いている最中なので、またまとめようと思います。