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) }
コード解説
- まずは実行対象のメソッドがあるクラスのKClass(
testSuite::class
)から、
KFunctionとして対象メソッドを取得(.memberFunctions.find { it.name == "createSampleData" }
)します - KFunctionのインスタンスが確保できていれば(
testMethod?.
)、
呼び出し結果をactualに保持するようにします(val actual = testMethod?.let {
) - 実行するためにアクセスを許可し(
it.isAccessible = true
)、
実行するインスタンスとメソッドに与えるパラメータ(100L)を指定して実行します(it.call(testSuite, 100L)
)
以上になります。
protectedのテストが面倒になった?
Javaの場合はprotectedメソッドであれば同一パッケージからすんなり呼べたので、テストが楽でよかったのですが、Kotlinの場合はちょっと工夫がいりそうです。 もうちょっと簡単な方法もありそうなのですが(PowerMockのWhiteboxクラス使うとか)、おいおい調べてみないといけないなという感じです。