Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return iterator from thenReturn mockito

Tags:

java

mockito

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()?

like image 395
learner Avatar asked Jan 07 '15 11:01

learner


People also ask

How do you mock an 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.

What does thenReturn do in Mockito?

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").

How do you make iterable?

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.


1 Answers

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.

like image 85
Mureinik Avatar answered Oct 17 '22 11:10

Mureinik