可以在Kotlin中使用Mockito吗?


78

我面临的问题是Matchers.anyObject()回报null。当用于仅接受非空类型的模拟方法时,它将导致引发“应该不为空”异常。

`when`(mockedBackend.login(anyObject())).thenAnswer { invocationOnMock -> someResponse }

模拟方法:

public open fun login(userCredentials: UserCredentials): Response

2
在kotlin社区网站上有一个关于如何避免此问题的讨论,请查看:devnet.jetbrains.com/thread/443551
SimY4

1
谢谢。好像devnet.jetbrains.com未被Google很好地索引。
atok 2015年

Answers:


75

有两种可能的解决方法:

private fun <T> anyObject(): T {
    Mockito.anyObject<T>()
    return uninitialized()
}

private fun <T> uninitialized(): T = null as T

@Test
fun myTest() {
    `when`(mockedBackend).login(anyObject())).thenAnswer { ... }
}

另一个解决方法是

private fun <T> anyObject(): T {
    return Mockito.anyObject<T>()
}

@Test
fun myTest() {
    `when`(mockedBackend).login(anyObject())).thenAnswer { ... }
}

这是有关此主题的更多讨论,其中首先提出了解决方法。


6
我相信SO也请您在答案中复制链接的内容,这样,如果链接失效,此答案仍然有用。
格雷格·科普夫

1
遗憾的是,在1.0.0-beta-4584中,此替代方法似乎不再起作用:kotlin.TypeCastException: null cannot be cast to non-null type X
nhaarman

@nhaarman对我来说很完美,能否请您指出确切的情况?
谢尔盖·马什科夫

3
它不适用于Kotlin 1.2.40。还有其他解决方法吗?
阿米尔·齐亚拉蒂

@nhaarman Kotlin 1.3.11,Mockito 2.7.12,Kotlin Mockito 1.5.0,2019年1月:解决方法1 ...很好,它可以解决。我的用例在给定/时间子句中。
milosmns

41

对于那些需要打字的人 any(type: Class<T>)

    private fun <T> any(type: Class<T>): T = Mockito.any<T>(type)

这将起作用并且类型检查也将发生!


4
可以避免传递类名:: class.java使用物化ARGS中的说法:inline fun <reified T> anyNonNull(): T = Mockito.any<T>(T::class.java)
泰雷兹普波阿劳霍

26

您可以使用以下帮助器函数在Kotlin中使用Mockito的any(),eq()和capture()匹配器:

/**
 * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
 * null is returned.
 *
 * Generic T is nullable because implicitly bounded by Any?.
 */
fun <T> eq(obj: T): T = Mockito.eq<T>(obj)

/**
 * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
 * null is returned.
 */
fun <T> any(): T = Mockito.any<T>()

/**
 * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
 * when null is returned.
 */
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()

请参阅Google的Android Architecture Blueprints存储库中的MockitoKotlinHelpers.kt



十分感谢!还可与最新版本的Mockito(v3.3.3)和Kotlin(v1.3.72)一起使用
Fatmajk

10

verify经常使用以确保传递给函数的参数也正确。

为此,仍然可以避免使用NPE,您可以使用kotlin的elvis运算符。例如: verify(mock).func(same(my_obj) ?: my_obj)

这样,由于实际验证了变量,mockito得到了满足,而由于传递了非null对象,因此使kotlin得到了满足。

我偶然发现的另一件事是模仿Mockito-kotlin库,它完全解决了这个问题 https://github.com/nhaarman/mockito-kotlin


1

使用时只需要返回一个非空结果Mockito.any();

Mockito.any() ?: 0
Mockito.any() ?: HashMap<Int,Int>()
Mockito.any() ?: {}

...


0

要扩展@makovkastar提供的答案,您可以提供一个可为空或不可为空的Matcher,如下所示:

/**
 * Matcher that returns null
 */
private inline fun <reified T> any(): T = Mockito.any<T>()

/**
 * Matcher never returns null
 */
private inline fun <reified T> any(type: Class<T>): T = Mockito.any(type)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.