android - 当模拟对象在 lambda 内部时单元测试失败,但是当它在 lambda 外部并在 lambda 内部使用时工作?
问题描述
我有一个对话框,我正在使用 Mockito / Mockito Kotlin 进行一些单元测试。
当用户单击对话框时,会向用户显示时间列表,然后他们的选择会分配该值,然后对其进行一些其他工作。
我有一个我模拟的 timeProvider 类,它只返回 currentTime。
这是发生选择的对话框的一部分
val currentTime = timeProvider.now()
dialogBuilder.setItems(context.resources.getStringArray(R.array.silenceTimes)) { _, which ->
val silenceUntil: Long = when (which) {
0 -> currentTime.plusMinutes(30).millis
1 -> currentTime.plusHours(1).millis
2 -> currentTime.plusHours(8).millis
3 -> currentTime.plusHours(24).millis
else -> 0
}
}
当代码在上面时,我的单元测试按预期工作。点击事件里面的逻辑触发,时间设置为currentTime加30分钟。
val items = arrayOf("0", "1", "2", "3")
val captor = argumentCaptor<DialogInterface.OnClickListener>()
val captor2 = argumentCaptor<DialogInterface>()
whenever(timeProvider.now()).thenReturn(currentTime)
whenever(dialogBuilder.setItems(eq(items), captor.capture())).thenReturn(dialogBuilder)
verify(dialogBuilder).setItems(eq(items), captor.capture())
captor.firstValue.onClick(captor2.capture(), eq(1))
但是当我在 click lambda 中有 timeProvider 时,它不再起作用并给我一个参数匹配器错误?
dialogBuilder.setItems(context.resources.getStringArray(R.array.silenceTimes)) { _, which ->
val currentTime = timeProvider.now()
val silenceUntil: Long = when (which) {
0 -> currentTime.plusMinutes(30).millis
1 -> currentTime.plusHours(1).millis
2 -> currentTime.plusHours(8).millis
3 -> currentTime.plusHours(24).millis
else -> 0
}
}
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 0 matchers expected, 2 recorded: -> at com.nhaarman.mockitokotlin2.KArgumentCaptor.capture(ArgumentCaptor.kt:105) -> at com.nhaarman.mockitokotlin2.MatchersKt.eq(Matchers.kt:34) This exception may occur if matchers are combined with raw values: //incorrect: someMethod(anyObject(), "raw String"); When using matchers, all arguments have to be provided by matchers. For example: //correct: someMethod(anyObject(), eq("String by matcher")); For more info see javadoc for Matchers class. at com.common.TimeProvider.now(TimeProvider.kt:8)
我不明白为什么代码可以在 lambda 之外的时间使用,但不能在 lambda 内部使用?
理想情况下,我不会在对话框之前设置它,因为谁知道在点击之前他们实际上会保持打开状态多长时间,而且,我将来可能会遇到这样的问题,不允许这样的解决方法?
解决方案
所以我仍然不确定这里发生了什么,但我意识到我总是回到位置 0 的哪个值(我认为他们 1 索引它)所以我尝试删除 captor2.capture
captor.firstValue.onClick(captor2.capture(), eq(1))
一旦我这样做了,并且只是传入 null,1 或 null,2 它就可以使用 lambda 中的值
¯_(ツ)_/¯
现在,我不需要另一个俘虏,所以我现在没事……
推荐阅读
- python - TensorFlow 1.5.4 无法通过 pip 获得
- azure - 从逻辑应用中的 Azure Key Vault 获取证书
- java - 当应用程序关闭或发送到后台时如何运行计数器?
- linux - 将文件内容复制到其他位置
- p5.js - 如何制作一个网格,使单元格在任何给定的纵横比下尽可能呈正方形?
- java - 如何在超类中获得泛型类?
- .net - 为什么在从 Visual Studio 调试 ASP.NET Core 源代码时看不到堆栈中间的局部变量
- javascript - react typescript setState是什么类型?
- javascript - 如何安装 binance-api-node
- winapi - 向 GUI 线程发布消息,同时影响 GetKeyState 的结果