Kotlinの実装のユニテでMockitoを使用したときに、表題のエラーでハマってしまったので、解決法を記事化しました。
エラーの内容
java.lang.IllegalStateException: Mockito.any() must not be null
- Mockito は
any()
のようなメソッドの呼び出しに対してnull
を返しますが、Kotlinではデフォルトでnullが許容されないため上記のようなエラーが発生してしまいます。 - 上記の問題は、
mockito-kotlin
を導入することで解決できます。
mockito-kotlinの導入
-
build.gradle.kts
に依存関係を追加
testImplementation("org.mockito.kotlin:mockito-kotlin:5.0.0")
mockito-kotlinの使用方法
- モックの作成方法
val mock : MyClass = mock()
- スタブの作成方法
mock.stub { on { stringValue() } doReturn "test" }
// or
given(mock.method(any())).willReturn("hoge")
- メソッド呼び出しの検証
verify(myClass, times(2)).doSomething(any())
- Argument Matchers
verify(myClass).setItems(argThat { size == 2 } )
- Argument Captors
val messageCaptor: ArgumentCaptor<String> = ArgumentCaptor.forClass(String::class.java)
argumentCaptor<String>().apply {
verify(myClass, times(2)).setItems(capture(messageCaptor))
assertEquals("test", messageCaptor.value)
}
(余談) KotlinでMockitoを用いる際の、final classに関する注意点(バージョン4.x.x
以前の場合)
- Kotlinではデフォルトで全てのクラスがfinal classとなリますが、バージョン
4.x.x
以前のMockitoはデフォルトでfinal classをモックできないため、下記のようなエラーが発生してしまいます。
Mockito cannot mock/spy because :
- final class
- 上記の問題点については、以下のいずれかを実施すれば解決できます
-
mockito-core
またはmockito-kotlin
のバージョンを5.0.0
以上に上げる-
5.0.0
以上のバージョンでは、デフォルトでfinal class/method のモックをサポートするようになったため。
-
-
mockito-core
の代わりに、final class/methodのモックをサポートするmockito-inline
を依存関係に含める。mockito-kotlin
を使用している場合は、mockito-inline
を依存関係に含める -
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
ファイルを作成し、mock-maker-inline
と記載し、final class/method用のモックメーカーを明示的にアクティブ化する。
-
まとめ
- Kotlinでは、Javaと同じようにはMockitoを使えない箇所がありますが、基本的に
mockito-kotlin
のバージョン5以降を使うことで解決できそうです