简体   繁体   中英

How to mock forEach behavior with Mockito

I want to make the following work, but I don't know how to mock forEach behavior properly. (The code is taken from a related question Testing Java enhanced for behavior with Mockito )

@Test
public void aa() {
  Collection<String> fruits;
  Iterator<String> fruitIterator;

  fruitIterator = mock(Iterator.class);
  when(fruitIterator.hasNext()).thenReturn(true, true, true, false);
  when(fruitIterator.next()).thenReturn("Apple")
      .thenReturn("Banana").thenReturn("Pear");

  fruits = mock(Collection.class);
  when(fruits.iterator()).thenReturn(fruitIterator);
  doCallRealMethod().when(fruits).forEach(any(Consumer.class));

  // this doesn't work (it doesn't print anything)
  fruits.forEach(f -> {
    mockObject.someMethod(f); 
  });

  // this works fine
  /*
  int iterations = 0;
  for (String fruit : fruits) {
    mockObject.someMethod(f); 
  }
  */

  // I want to verify something like this
  verify(mockObject, times(3)).someMethod(anyString());
}

Any help will be very appreciated.

The method forEach of the Collection interface is a "defender" method; it does not use Iterator but call the Consumer passed to the method.

If you are using Mockito version 2+ (*), you can ask the default method forEach of the Collection interface to be called:

Mockito.doCallRealMethod().when(fruits).forEach(Mockito.any(Consumer.class));

Note that the "defender" method is actually going to request an Iterator to traverse the collection, hence will use the Iterator you mocked in your test. It wouldn't work if no Iterator was provided by the mocked collection, as with when(fruits.iterator()).thenReturn(fruitIterator)

(*): Mockito has added the possibility to support Java 8 default ("defender") method since version 2 - you can check the tracking issue here .

Iterator mockIterator = mock(Iterator.class);
doCallRealMethod().when(fruits).forEach(any(Consumer.class));
when(fruits.iterator()).thenReturn(mockIterator);
when(mockIterator.hasNext()).thenReturn(true, false);
when(mockIterator.next()).thenReturn(mockObject);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM