I have a dialog that I'm doing some unit tests on using Mockito / Mockito Kotlin.
When the user clicks on the dialog, the user is shown a list of times, and then their selection assigns the value and then does some other work with it.
I have a timeProvider class that I've mocked which just returns the currentTime.
This is the part of the dialog where the selection happens
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
}
}
When the code is above, my unit test works as expected. The logic inside the click event triggers, and the time is set to the currentTime plus 30 minutes.
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))
But when I have the timeProvider inside the click lambda, it no longer functions and gives me an argument matcher error?
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)
I can't figure out why the code works with the time outside the lambda, but not inside the lambda?
Ideally I wouldn't set it before the dialog because who knows how long they'd actually keep it open before clicking, but also, I might run into problems like this in the future which don't allow a workaround like that?