Kotlin lambda回调的单元测试

Mar*_*tek 12 java lambda unit-testing mockito kotlin

假设我们有以下功能要测试

fun loadData(dataId: Long, completion: (JsonElement?, Exception?) -> Unit) {
    underlayingApi.post(url = "some/rest/url",
            completion = { rawResult, exception ->
                val processedResult = processJson(rawResult)
                completion(processedResult, exception)
            })
}
Run Code Online (Sandbox Code Playgroud)

我很清楚如何模拟,注入,存根和验证调用 underlayingApi.

如何验证通过返回的结果 completion(processedResult, exception)

Mar*_*tek 8

要测试lambda行为,underlayingApi必须模拟通过这样的InvoactionOnMock对象调用lambda的行为。

    `when`(underlayingApi.post(eq("some/rest/url"),
                               any())).thenAnswer {
        val argument = it.arguments[1]
        val completion = argument as ((rawResult: String?, exception: Exception?) -> Unit)
        completion.invoke("result", null)
    }
Run Code Online (Sandbox Code Playgroud)

这导致在测试对象内调用回调。现在,检查被测对象的回调是否正常工作,以这种方式进行验证。

    objUnderTest.loadData(id,
                          { json, exception ->
                              assert....
                          })
Run Code Online (Sandbox Code Playgroud)

  • 这样,您可能会收到“未经检查的演员表”棉绒警告。为了防止这种情况,您可以改用`getArgument()`函数。例如:`val arguments = it.getArgument <(((rawResult:String ?, exception:Exception?)-> Unit)>(1)` (3认同)

Seb*_*ian 5

在马丁的答案的基础上,这是我不加棉绒警告的方法:

import com.nhaarman.mockito_kotlin.*

@Test
fun loadData() {
    val mockUnderlyingApi: UnderlayingApi = mock()
    val underTest = ClassBeingTested()
    underTest.underlayingApi = mockUnderlyingApi

    whenever(mockUnderlyingApi.post(eq("some/rest/url"), any())).thenAnswer {
        val completion = it.getArgument<((rawResult: String?, exception: Exception?) -> Unit)>(1)
        completion.invoke("result", null)
    }

    underTest.loadData(0L,
            { jsonElement, exception ->
                // Check whatever you need to check
                // on jsonElement an/or exception
            })
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢最重要的一行 `import com.nhaarman.mockito_kotlin.*`。这是库 github:https://github.com/nhaarman/mockito-kotlin。使用 `2.1.0` 版本,只需要将导入更改为 `import com.nhaarman.mockitokotlin2.*` (2认同)