Mockito的论证捕获者行为

时间:2018-01-19 14:01:01

标签: java mockito

我面临的问题是我需要跟踪某些方法的调用,但只能使用指定的参数参数。请参阅下面的问题

@Test
public void simpleTest() {
    ArgumentCaptor<Pear> captor = ArgumentCaptor.forClass(Pear.class);
    Action action = mock(Action.class);
    action.perform(new Pear());
    action.perform(new Apple());
    verify(action, times(1)).perform(captor.capture());
}

static class Action {

    public void perform(IFruit fruit) {}

}
static class Pear implements IFruit {}
static class Apple implements IFruit {}

interface IFruit {}

但是得到:

org.mockito.exceptions.verification.TooManyActualInvocations: 
action.perform(<Capturing argument>);
Wanted 1 time:
But was 2 times. Undesired invocation:
..

我做错了什么? Mockito v 1.10

说实话,这只是例如,我的代码更复杂,我不知道,Apple.class会调用多少次执行。这对我来说并不重要。我只需要验证执行调用(Pear.class)

UPD: 我需要验证Pear.class的方法被调用一次。让我们假设Action是Transaction并且执行是save(DomainObject)。所以我需要确保save(MyDomainObject)被调用一次,但无论之前保存了多少个对象。这个动作对于Test来说是原子的,我不能在这些操作之间重置模拟

3 个答案:

答案 0 :(得分:3)

使用自定义捕获器类的解决方法

  @Test
  public void simpleTest() {
    MyArgumentCaptor pearCaptor = new MyArgumentCaptor(Pear.class);
    Action action = mock(Action.class);

    action.perform(new Pear());
    action.perform(new Apple());

    verify(action, times(1)).perform((IFruit) argThat(pearCaptor));

    System.out.println(pearCaptor.getMatchedObj());
  }


  class MyArgumentCaptor extends InstanceOf {
    private Object matchedObj;

    MyArgumentCaptor(Class<?> clazz) {
      super(clazz);
    }

    @Override
    public boolean matches(Object actual) {
      boolean matches = super.matches(actual);
      if (matches) {
        matchedObj = actual;
      }
      return matches;
    }

    Object getMatchedObj() {
      return matchedObj;
    }
  }

答案 1 :(得分:2)

要使用Pear实例参数验证通话次数,您可以使用:

verify(action, times(1)).perform(isA(Pear.class));

比照。 Mockito. Verify method param to be a paticular class

请注意,自Mockito 2.1起,以下内容也适用:

verify(action, times(1)).perform(any(Pear.class));

比照public static T any(Class type)

  

...这是别名:isA(Class)...

     

...因为mockito 2.1.0 any()和anyObject()不再是别名   这种方法。

答案 2 :(得分:0)

您正在调用操作两次,但期待一次调用(times(1))。如果被调用两次,请尝试使用times(2),如果您不关心调用它的次数,请忽略它。

action.perform(new Pear());
action.perform(new Apple());