如何使用Mockito模拟每个行为

时间:2018-03-21 12:12:46

标签: java mocking mockito

我想做以下工作,但我不知道如何正确地模拟每个行为。 (代码取自相关问题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());
}

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

forEach界面的方法Collection是&#34;后卫&#34;方法;它不使用Iterator,而是调用传递给方法的Consumer

如果您使用的是Mockito版本2+(*),则可以要求调用forEach接口的默认方法Collection

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

请注意&#34;后卫&#34;方法实际上是要求Iterator遍历集合,因此将使用您在测试中模拟的Iterator。如果被模拟的集合没有提供Iterator,那么它就无法工作,就像使用when(fruits.iterator()).thenReturn(fruitIterator)

一样

(*):自第2版以来,Mockito已添加了支持Java 8默认(&#34; defender&#34;)方法的可能性 - 您可以检查跟踪问题here

答案 1 :(得分:0)

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);