LoginSignup
1
2

More than 3 years have passed since last update.

KotlinでMockitoのArgumentCaptorが使えない

Last updated at Posted at 2020-10-14

なぜか日本語の情報が乏しかったのでメモしておきます。

KotlinではArgumentCaptorが使えない!!

Javaの代表的なモックライブラリMockito。いろんなことができるMockitoですがその中の一つにモックのメソッドに渡したパラメータの検証を可能にするArgumentCaptorがあります。

Mockito自体は当然Kotlinでも使えるのですが、ArgumentCaptorはKotlinでは使えない!!(場合が多い)

エラーの例

具体的にはこんなコードで実行すると

テスト対象
class Sample {
    fun testTarget(message:String, value:Int) {
        println("%s%d".format(message,value))
    }
}
テストコード
@RunWith(PowerMockRunner::class)
@PrepareForTest(Sample::class)
class SampleTest {
    val instance = PowerMockito.mock(Sample::class.java)
    val messageCaptor: ArgumentCaptor<String> = ArgumentCaptor.forClass(String::class.java)
    val valueCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)

    @Test
    fun test() {
        instance.testTarget("This is", 3)

        Mockito.verify(instance,Mockito.times(1)).testTarget(messageCaptor.capture(),valueCaptor
            .capture())

        Assert.assertEquals("This is", messageCaptor.value)
        Assert.assertEquals(1, valueCaptor.value)
    }

こんなエラーが出力されます。

java.lang.IllegalStateException: messageCaptor.capture() must not be null

これの原因はエラーメッセージにもあるように「Non-NullableなパラメータにNullが入ったから」ですね。

KotlinのNull安全な仕様が裏目に……

そう、ArgumentCaptor.capture()Nullを返すのです。JavaはパラメータのNullチェックをしないので問題ありませんでしたが、KotlinはNullチェックしてくれます。その優しさが裏目に出てしまったのです。

もちろんメソッドのパラメータをNon-Nullableにすれば実行できます。しかしそれでは本末転倒です。

mockito-kotlinを使う

その解決策がmockito-kotlinを使うことです。

mockito-kotlinのcapture()を使うことでキャプチャしつつテストメソッドには値をそのまま渡すことができます。

修正後のテストコード
@RunWith(PowerMockRunner::class)
@PrepareForTest(Sample::class)
class SampleTest {
    val instance = PowerMockito.mock(Sample::class.java)
    val messageCaptor: ArgumentCaptor<String> = ArgumentCaptor.forClass(String::class.java)
    val valueCaptor: ArgumentCaptor<Int> = ArgumentCaptor.forClass(Int::class.java)

    @Test
    fun test() {
        instance.testTarget("This is", 3)

        //ArgumentCaptor.capture()は使わずにmockito_kotlin.capture()を使う
        //mockito_kotlin.capture()の引数はArgumentCaptorのインスタンスをそのまま入れれば良い
        Mockito.verify(instance,Mockito.times(1)).testTarget(capture(messageCaptor),capture(valueCaptor))

        Assert.assertEquals("This is", messageCaptor.value)
        Assert.assertEquals(3, valueCaptor.value)
    }
}

お手軽簡単ですね。

mockito-kotlinはMockitoをよりKotlinぽく使うためのライブラリのようですが、私のように「Javaで覚えた書き方そのまま使いたい」という面倒くさがり屋にも大変有用です。

参考

Mockito ArgumentCaptor for Kotlin function

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2