Java
Kotlin
unittest
Mockito

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でのキャストでは実行時にも動作するのです。