White Box技術部

WEB開発のあれこれ(と何か)

Kotlinのリフレクション(protected/privateメソッド呼び出し)

protectedメソッドへのアクセス

Kotlinにおいてprotectedのアクセス修飾子は、Javaと異なり同一パッケージからのアクセスを許容しません。 そのため、テストコードなどでprotectedのメソッドを実行したい場合は、リフレクションを使う必要があります。

継承してテストするという方法もありそうですが、今までしなかった発想なのでどうなんですかね。

リフレクションによる実行

例えばTestDataRepositoryにcreateSampleDataというLongのパラメータを1つ取り、SampleDataクラスを返却するprotectedのメソッドあるとした場合、以下が対象のメソッドを実行するコードになっています。

var testSuite = TestDataRepository()

val testMethod = testSuite::class.memberFunctions.find { it.name == "createSampleData" }
val actual = testMethod?.let {
    it.isAccessible = true
    it.call(testSuite, 100L)
}

コード解説

  1. まずは実行対象のメソッドがあるクラスのKClass(testSuite::class)から、
    KFunctionとして対象メソッドを取得(.memberFunctions.find { it.name == "createSampleData" })します
  2. KFunctionのインスタンスが確保できていれば(testMethod?.)、
    呼び出し結果をactualに保持するようにします(val actual = testMethod?.let {
  3. 実行するためにアクセスを許可し(it.isAccessible = true)、
    実行するインスタンスとメソッドに与えるパラメータ(100L)を指定して実行します(it.call(testSuite, 100L)

以上になります。

protectedのテストが面倒になった?

Javaの場合はprotectedメソッドであれば同一パッケージからすんなり呼べたので、テストが楽でよかったのですが、Kotlinの場合はちょっと工夫がいりそうです。 もうちょっと簡単な方法もありそうなのですが(PowerMockのWhiteboxクラス使うとか)、おいおい調べてみないといけないなという感じです。