Java8 stream of iterator is not mockable?

3,394 views
Skip to first unread message

Felix Gao

unread,
Aug 12, 2016, 4:50:52 AM8/12/16
to mockito
Hi all I am trying to mock an iterator
@Test
public void scratch(){
List<String> testlist = new ArrayList<String>(){{
add("1");
}};

Iterator<String> iter = mock(Iterator.class);
when(iter.hasNext()).thenReturn(true, false);
when(iter.next()).thenReturn("1");

List<String> resultList = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED), false)
.collect(Collectors.toList());

assertThat(resultList.size(), is(1));
assertThat(resultList.get(0), is("1"));
}


this code will not work but
@Test
public void scratch(){
List<String> testlist = new ArrayList<String>(){{
add("1");
}};

List<String> resultList = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(testlist.iterator(), Spliterator.ORDERED), false)
.collect(Collectors.toList());

assertThat(resultList.size(), is(1));
assertThat(resultList.get(0), is("1"));
}

will work just fine

any help?

Thanks,

Felix












Malte Finsterwalder

unread,
Aug 12, 2016, 5:36:08 AM8/12/16
to mockito
I can't help you directly, but here is what I would so.

1) Do not mock Iterator! Do you really want to test the interaction between Streams and Iterator? I don't think so. The Java lib is tested and works fine. ;-) Use a Collection or Stream and you are done with it. 

2) Should you really, really, really need to mock an Iterator, then you need to read the code what streams will do with the iterator. And you need to mock everything correctly, that it works as expected.

Greetings,
   Malte

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+unsubscribe@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.
To view this discussion on the web visit https://groups.google.com/d/msgid/mockito/3bb00070-98e5-4349-80f7-fa1e47e298e8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brice Dutheil

unread,
Aug 12, 2016, 6:09:22 AM8/12/16
to moc...@googlegroups.com

I agree with Malte on this type of things. Don’t mock types you don’t own.

Technically the reason is that the Stream that uses the created Spliterator does not invoke hasNext() or next() directly ; instead it invokes the default method forEachRemaining, which is not mocked thus do nothing as it is a mock.

Adding this stub make the test work (mockito 2 beta) :


doAnswer(CALLS_REAL_METHODS).when(iter).forEachRemaining(any());

But in the end this behaviour is subject to JDK implementation which is not under your or our control. For that reason the preferred way would be to use a concrete type.

Cheers,
— Brice

Message has been deleted

Eric Lefevre-Ardant

unread,
Aug 12, 2016, 3:20:18 PM8/12/16
to moc...@googlegroups.com
Not sure why that function might be a problem.
Just make sure that 'iter' is initialised to an appropriate, fully instantiated, iterator, and you're fine.

On 12 August 2016 at 19:27, Felix Gao <guoh...@gmail.com> wrote:
Thank Brice and Malte on the do not mock iterator, but unfortunately, I need to test this function.

List<UserRole> getUserRolesWithWildcardAppName(
UserInfo.Username userID,
Application.Name applicationName
) {
List<UserRole> resultList;
try {
Result<com.intuit.wasabi.repository.cassandra.pojo.UserRole> result =
userRoleAccessor.getUserRolesByUserIdWithWildcardAppName(userID.getUsername());
        resultList = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED), false)
        .collect(Collectors.toList());    } catch (ReadTimeoutException | UnavailableException | NoHostAvailableException e) {
throw new RepositoryException("Could not retrieve permissions for user \"" + userID + "\" and application "
+ "\"" + applicationName + "\"", e);
}
return resultList;
}
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.
To view this discussion on the web visit https://groups.google.com/d/msgid/mockito/3bb00070-98e5-4349-80f7-fa1e47e298e8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+unsubscribe@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.

Malte Finsterwalder

unread,
Aug 12, 2016, 4:47:29 PM8/12/16
to mockito
I can't see where "iter" comes from.Where is it passed in or defined?
And even if you need to test a method that uses an iterator, why not just fill a collection in your test and hand the real iterator from the collection to the code under test? Like Eric said.

Greetings,
   Malte

On 12 August 2016 at 19:27, Felix Gao <guoh...@gmail.com> wrote:
Thank Brice and Malte on the do not mock iterator, but unfortunately, I need to test this function.

List<UserRole> getUserRolesWithWildcardAppName(
UserInfo.Username userID,
Application.Name applicationName
) {
List<UserRole> resultList;
try {
Result<com.intuit.wasabi.repository.cassandra.pojo.UserRole> result =
userRoleAccessor.getUserRolesByUserIdWithWildcardAppName(userID.getUsername());
        resultList = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iter, Spliterator.ORDERED), false)
        .collect(Collectors.toList());    } catch (ReadTimeoutException | UnavailableException | NoHostAvailableException e) {
throw new RepositoryException("Could not retrieve permissions for user \"" + userID + "\" and application "
+ "\"" + applicationName + "\"", e);
}
return resultList;
}




On Friday, August 12, 2016 at 3:09:22 AM UTC-7, Brice wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.
To view this discussion on the web visit https://groups.google.com/d/msgid/mockito/3bb00070-98e5-4349-80f7-fa1e47e298e8%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.

To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+unsubscribe@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at https://groups.google.com/group/mockito.

Felix Gao

unread,
Aug 12, 2016, 5:40:56 PM8/12/16
to mockito
Thanks Eric and Malte, I will just create the collection like you guys mentioned.
Reply all
Reply to author
Forward
0 new messages