Ccmmutty logo
Commutty IT
0 pv3 min read

Android の Unit test で java.lang.NoSuchMethodException が発生した人を救いたかった

https://cdn.magicode.io/media/notebox/f302a856-2f0f-4938-b9ff-60283b706847.jpeg

シチュエーション

某 Kotlin で実装された Android TV アプリのテスト コードを書いていた際に「private 関数の中までテストしてカバレッジ 100 % を目指す必要がある。リフレクションを用いればプライベート関数内の挙動をテストできる」と教えていただきました。

IMO

private 関数をテストしなくてもいい状況を作った方がいい説 🧐
public なクラスに処理を外出しするなど 💭

困った点

Reflection で private 関数の中身を実行できている筈が java.lang.NoSuchMethodException が発生 😵

対処方法

dependencies {
    implementation(kotlin("reflect"))
}
を追記すると解決しました。

サンプル

import androidx.lifecycle.ViewModel

class SampleViewModel : ViewModel() {
    /**
     * @return 文字列
     */
    private fun getText() = "じゃあそこ試合決定で"
}
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

class ExampleUnitTest {
    private lateinit var sampleViewModel: SampleViewModel

    @Before
    fun setUp() {
        sampleViewModel = SampleViewModel()
    }

    @Test
    fun reflection() {
        // プライベート関数を取得
        val method = sampleViewModel.javaClass.getDeclaredMethod("getText").also { method ->
            method.isAccessible = true // プライベート関数へのアクセスを許可
        }
        // 関数を呼び出して戻り値を取得
        val actual = method.invoke(sampleViewModel) as String
        // 期待する結果と比較
        assertEquals("じゃあそこ試合決定で", actual)
    }
}

追加検証

私有 MacBook Pro の Android Studio Koala にて Android アプリと TV の [New Project] を作成して上記ユニット テストを実行してみたところ implementation "org.jetbrains.kotlin:kotlin-reflect:$reflect_version" の記載をせずともユニテが通りました ◎
その某プロジェクトでの compileSdktargetSdk, Kotlin 諸々のバージョンや依存しているライブラリによって発生していたのかもしれません 🤔
何が要因で Exception が発生していたのか真相が闇に葬られました 👼 すみませんの世界です 🙇‍♀️

Discussion

コメントにはログインが必要です。