Hi I have a class A
implementing Iterable
.
I have this code to stub an object of this class:
First way:
A source = mock(A.class);
final List<String> documents = getList();
when(source.iterator()).thenAnswer(new Answer<Iterator<String>>() {
@Override
public Iterator<String> answer(final InvocationOnMock invocation) throws Throwable {
return documents.iterator();
}
});
Second way:
A source = mock(A.class);
final List<String> documents = getList();
when(source.iterator()).thenReturn(getList().iterator());
The first way returns a new Iterator
on every call to source.iterator()
but the second one returns the same Iterator
object. So if I use second way to stub the source object, I get an empty iterator in subsequent calls to source.iterator()
.
Why is this happening? Shouldn't Mock return a new Iterator
on every call to source.iterator()
?
Mock the iterable's (the set) iterator() method to return a mock iterator. Mock the iterator's hasNext() method to return true N times followed by false where N is the number of values that you want the iterator to return. Mock the iterator's next() method to return the N elements in order.
thenReturn or doReturn() are used to specify a value to be returned upon method invocation. //”do something when this mock's method is called with the following arguments” doReturn("a").
To make an array iterable either you need to convert it to a stream or as a list using the asList() or stream() methods respectively. Then you can get an iterator for these objects using the iterator() method.
Inlining code can sometimes be confusing. Let's unwrap the second block of code:
A source = mock(A.class);
final List<String> documents = getList();
final Iterator<String> iter = getList().iterator()
when(source.iterator()).thenReturn(iter);
Now, it's easier to understand. The same iter
object is always returned, and hence it retains it's state. The fact that before the change above mockito had a function call in the brackets is inconsequential - mockito has an object passed to it, which it stores internally, and returns when required. It cannot "remember" that this object was produced by calling a function unless it has the actual code to execute it - for example, like you did in the first snippet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With