For the given code below, in Kotlin, it's not possible to execute the function forEach
(or anything similar, map
, filter
, so on...) because BarList
is mocked. So the native implementation of forEach
and relatives are not being called. After a bit of search on the internet I came with this:
public class BarList<E> extends AbstractList<E> implements OrderedBarCollection<E> {
//...
}
//...
val mockedList: BarList<Foo> = mockBarList()
val fooList = listOf(Foo())
`when`(mockedList.iterator()).thenReturn(fooList.iterator())
`when`(mockedList.size).thenReturn(fooList.size)
com.nhaarman.mockito_kotlin
.doCallRealMethod()
.`when`(mockedList)
.forEach(Mockito.any<Consumer<Foo>>()) //Attempt to call the Consumer.
mockedList.forEach { foo ->
//Not executing
}
I tried this above based on the answer of this question: https://stackoverflow.com/a/49407513/2430555
I also tried:
com.nhaarman.mockito_kotlin.doCallRealMethod().`when`(mockedList).forEach(any())
But it's causing:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
//...
The definition of forEach
in the Kotlin source code is:
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit
I think I should replace any()
with something that matches action: (T) -> Unit
, but I am not sure how to do this.
I don't mind to use interactor if needed, but I need to at least make forEach
run as expected. Could you guys please help me?
Regards,
Pedro
The solution is to use thenAnswer
instead of thenReturn
for the mocked list.
`when`(mockedList.iterator()).thenAnswer { fooList.iterator() }
Reason:
Author: Tobias Berger
an iterator is only good for going through the list once. Therefore you usually get a new one every time you call the iterator() function. If you mock that with thenReturn(messageList.iterator()) , it will just call that once on messageList and reuse that iterator instance every time you try to get one for your mock. Once your first loop over this iterator is finished, it will always say it has no more items. With thenAnswer you define a supplier that is called each time your mocked function is used, providing a new iterator for each call (as would be expected)