【问题标题】:Mock kotlin function as parameter in Android模拟 kotlin 函数作为 Android 中的参数
【发布时间】:2018-04-11 08:15:49
【问题描述】:

我需要测试一个接受另一个函数作为参数的 Kotlin 函数。 这个类看起来像这样:

class MyClass(val myInstance: MyObject) {

    fun toBeTested(text: String, number: Int) {
        myInstance.doSomething(text, otherFunction(number))
        ...
    }
}

到目前为止我的测试是这样的

@Test
fun testFunction() {
    val mockInstance = mock(MyObject::class.java)

    myClass.toBeTested("test", 15)
}

我想用verify(mockInstance, times(1)).doSomething(),但是我需要在doSomething里面指定它需要的参数,我不知道如何指定函数。

这是正确的方向吗?或者我应该采取其他方式(也许是重新组织代码或做一些其他的魔法)?

非常感谢

【问题讨论】:

    标签: android unit-testing lambda kotlin mockito


    【解决方案1】:

    Mockito.any() 需要Class<T> 作为第一个参数,因此您要做的是获取() -> UnitClass 实例。 Kotlin 不允许您编写 (() -> Unit)::class.java,但它确实允许您访问 () -> Unit 的底层类:Function0

    所以要获得您需要的Class<() -> Unit>,您可以执行以下操作:

    val f : Class<() -> Unit> = Function0::class.java as Class<Function0<Unit>>
    

    您可以将此类传递给any 调用:

    verify(mockInstance, times(1)).doSomething(any(f))
    

    现在这不是很漂亮,因此您可以定义一个自定义的 any() 函数来为您完成所有这些魔法:

    inline fun <reified T : Any> myAny() = Mockito.any(T::class.java)
    

    这使您可以执行以下操作:

    verify(mockInstance, times(1)).doSomething(myAny<() -> Unit>())
    // or:
    verify(mockInstance, times(1)).doSomething(myAny())
    

    这就是 Mockito-Kotlin 在后台为您所做的事情。

    【讨论】:

    • 免责声明:我是 mockito-kotlin 的作者
    • 嘿@nhaarman,谢谢你的回复。实际上,我已经关注了您的工作并尝试实施它(顺便说一句,感谢您为社区所做的事情)。问题是,当我这样做时,测试失败并显示“myAny() must not be null”这一行,因为我的 doSomething 函数接受不可为空的参数
    • 是的,我检查过了,但是createInstance 需要nonNullProvider,而NullCasterInstanceCreator 等需要更多类或导入您的库:)我试图看看是否有更快的方法来解决它
    • 实际上,即使导入您的库并将其“hack”与createInstance 一起使用,问题仍然存在并且测试失败并使用Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多