【问题标题】:Mockito's Argument Captor BehaviorMockito 的参数捕获者行为
【发布时间】:2018-01-19 14:01:01
【问题描述】:

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

@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 会调用多少次 perform。对我来说没关系。我只需要验证 perform(Pear.class) 的调用

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

【问题讨论】:

  • 你调用了两次,然后试图验证你只调用了一次?
  • @Berger 在他的情况下,测试通过应该是次(2)次
  • 但我只想验证参数类型为 Pear.class 的方法的调用。任何想法怎么做?
  • 尝试verify(action, times(1)). perform(argumentThat(yourImplementation) )检查参数

标签: java mockito


【解决方案1】:

要使用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() 不再是 这个方法。

【讨论】:

  • 只是为了澄清一点:any() 实际上匹配任何(事物)。那里的类​​不以任何方式限制它,它只是为了兼容 Java 的类型检查。
  • @FlorianSchaetz :刚刚搜索了这一点,似乎从 Mockito 2.1 开始,any(Class)isA(Class) 的别名,而不是 any()/anyObject() 的别名,请参阅:static.javadoc.io/org.mockito/mockito-core/2.13.0/org/mockito/…
【解决方案2】:

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

  @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;
    }
  }

【讨论】:

  • 这两行代码节省了我的时间。非常感谢...... verify(action, times(1)).perform((IFruit) argThat(pearCaptor)); System.out.println(pearCaptor.getMatchedObj());
【解决方案3】:

您调用了两次操作,但期待一次调用 (times(1))。如果它被调用两次,请尝试使用times(2),如果您不在乎调用多少次,请忽略它。

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

【讨论】:

  • 老实说这只是一个例子,我的代码更复杂,我不知道,Apple.class 将调用多少次执行。对我来说没关系。我只需要验证 perform(Pear.class) 的调用
  • 如果你不在乎方法被调用多少次,更新描述。
  • 我需要验证 Pear.class 的方法是否被调用过一次。让我们假设 Action 是 Transaction 并且 perform 是 save(DomainObject)。所以我需要确保 save(MyDomainObject) 被调用一次,但无论之前保存了多少个对象。此操作对于 Test 来说是原子的,我无法在这些操作之间重置模拟
猜你喜欢
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2023-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多