android - 使用 Kotlin 在 Android 中测试 lambda 函数

标签 android unit-testing lambda kotlin mockito

我需要对函数 doClassAction 进行单元测试,并在其中调用对象 store 上的函数 doStoreAction。 此 doStoreAction 接受两个参数,一个整数和一个函数,如下例所示

class MyStore() {

    fun doStoreAction(num: Int, callback: (text: String) -> Unit) {
        // It does something 
        // ...
        // and when it's done it calls the callback

        return callback("some text")
    }
}

class MyClass(private val store: MyStore,
              private val objectX: MyObject) {

    fun doClassAction(num: Int) {
        store.doStoreAction(num) { callbackResult ->
            // Action (potentially asynchronous)
            // that will happen after obtaining the value via the callback

            objectX.doObjectAction(callbackResult)
        }
    }
}

我正在使用 Mockito,到目前为止我的测试有以下几行

@Test
fun doClassActionTest() {
    val mockStore = mock(MyStore::class.java)
    val mockObject = mock(MyObject::class.java)
    val class = MyClass(mockStore, mockObject)
    class.doClassAction(42)
}

但它没有编译,因为对方法的调用没有指定回调...我不想覆盖它,因为我希望测试使用原始的并验证内部的东西是否被正确调用,比如:

when(objectX.doObjectAction(anyString())).doNothing()
verify(objectX, times(1)).doObjectAction(callbackResult)

有没有一种方法可以调用该方法并将回调响应模拟为我在测试中设置的值,但仍然让它通过原始代码流?

最佳答案

经过几天的尝试和阅读,我终于找到了一个可行的解决方案,我将在这里分享给遇到同样问题的人

@Test
fun doClassActionTest() {
    val mockStore = mock(MyStore::class.java)
    val mockObject = mock(MyObject::class.java)
    val myClass = MyClass(mockStore, mockObject)
    val input = 42
    val resultCallback = "test result"

    `when`(mockStore.doStoreAction(any(), any())).then { invocation ->
        (invocation.arguments[1] as (String) -> Unit).invoke(resultCallback)
    }

    myClass.doClassAction(input)

    verify(mockObject, only()).doObjectAction(resultCallback)
}

这里需要注意的是,请记住在 Kotlin 中将您正在模拟的类和这些类调用的方法作为 open 放置,否则可能会出现误报

附言我还使用了从 mockito-kotlin 中提取的一些内联函数图书馆如:

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

inline fun <reified T : Any> createInstance(): T = createInstance(T::class)

fun <T : Any> createInstance(kClass: KClass<T>): T = castNull()

@Suppress("UNCHECKED_CAST")
private fun <T> castNull(): T = null as T

关于android - 使用 Kotlin 在 Android 中测试 lambda 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50256747/

相关文章:

python - assertRaises() 在引发多个异常的测试用例中

ajax - Lambda 使用 contains 查询获取多条记录返回空

android - android phonegap 应用程序中未显示背景图片

php - 使用json在android中通过php更新mysql

Android 如何将媒体图片移动到另一个文件夹?

android - 获取Json数组中的数据并发送给服务器

angular - 如何使用自己的依赖项测试内部嵌套组件的 Angular 2 组件? (TestBed.configureTestingModule)

c# - 使用服务进行验证时如何对 IValidatableObject Validate 进行单元测试?

java - 如何在 Java8 Lambda 中编写这个 for 循环

C++11 "overloaded lambda"带有可变参数模板和变量捕获