Edited at

KotlinでMockitoのany()などのArgumentMatchersを使う方法

More than 1 year has passed since last update.

KotlinでMockitoのany()isA()を利用するとjava.lang.IllegalStateException: Mockito.any() must not be null

が発生します。

これらのメソッドがnullを返すため(プリミティブ型であればデフォルト値を返すのでこのエラーは起きません)で、Null安全なKotlinではエラーになります。

検証対象のメソッド引数をNullableにすれば当然解決しますが、それはやりたくないですよね。

例えば、以下の部分をモックにして引数を検証したいです。

transition.onNext(TransitionType.Success())

実際のコードとテストの検証時では別のインスタンスなので、同じクラスかどうか検証したいです。

なので、こう書きます。

Mockito.doNothing().`when`(mockEventBus).onNext(Mockito.isA(TransitionType.Success::class.java))

これだとエラーになります。


解決方法

以下のnullReturn()のようにキャストすれば動作するようになりました。

class TestUtils private constructor() {

companion object {
fun <T> isA(type: Class<T>): T {
Mockito.isA<T>(type)
return nullReturn()
}

fun <T> any(): T {
Mockito.any<T>()
return nullReturn()
}

private fun <T> nullReturn(): T = null as T
}
}

Mockito.doNothing().`when`(mockEventBus).onNext(TestUtils.isA(TransitionType.Success::class.java))

理由はわかりませんが、Kotlinは null as String のようにnullをキャストするとコンパイラーnullチェックを回避できます。

NotNullなクラスにキャストしているから、実際はnullでもNotNullとして判断されているのでしょうか。

(実行時にはTypeCastExceptionで落ちます。)

そして、何故かGenericsでのキャストでは実行時にも動作するのです。