【问题标题】:Is it possible to use Mockito in Kotlin?是否可以在 Kotlin 中使用 Mockito?
【发布时间】:2015-07-30 01:50:15
【问题描述】:

我面临的问题是Matchers.anyObject() 返回null。当用于模拟只接受不可为空类型的方法时,它会导致抛出“不应为空”异常。

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

模拟方法:

public open fun login(userCredentials: UserCredentials): Response

【问题讨论】:

  • 在 kotlin 社区网站上有一个关于如何避免这个问题的讨论,请查看:devnet.jetbrains.com/thread/443551
  • 谢谢。似乎 devnet.jetbrains.com 没有被谷歌很好地索引。

标签: java mocking mockito kotlin


【解决方案1】:

有两种可能的解决方法:

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 { ... }
}

这里是关于这个主题的some more discussion,这里首先建议了解决方法。

【讨论】:

  • 我相信 SO 恳请您在答案中复制链接的内容,以便如果链接失效,此答案仍然有用。
  • 遗憾的是,在 1.0.0-beta-4584 中,这种解决方法似乎不再起作用:kotlin.TypeCastException: null cannot be cast to non-null type X
  • @nhaarman 非常适合我,能否请您指出具体情况?
  • 它不适用于 Kotlin 1.2.40。没有其他解决方法吗?
  • @nhaarman Kotlin 1.3.11,Mockito 2.7.12,Kotlin Mockito 1.5.0,2019 年 1 月:解决方法 1……嗯,它可以解决。我的用例在 given/when 子句中。
【解决方案2】:

对于那些需要输入any(type: Class&lt;T&gt;)的人

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

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

【讨论】:

  • 可以避免使用具体化的 args 在参数中传递 ClassName::class.javainline fun &lt;reified T&gt; anyNonNull(): T = Mockito.any&lt;T&gt;(T::class.java)
【解决方案3】:

您可以使用以下辅助函数在 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 架构蓝图存储库中的 MockitoKotlinHelpers.kt

【讨论】:

【解决方案4】:

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

要做到这一点,并且仍然避免 NPE,您可以使用 kotlin 的 elvis 运算符。 例如: verify(mock).func(same(my_obj) ?: my_obj)

这样,mockito 是满意的,因为它实际上验证了变量,而 kotlin 是满意的,因为我们传递了一个非 null 对象。

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

【讨论】:

    【解决方案5】:

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

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

    ...

    【讨论】:

      【解决方案6】:

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

      /**
       * 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)
      

      【讨论】:

      • 对我来说private fun &lt;T&gt; any(): T = Mockito.any() 也有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      相关资源
      最近更新 更多