Mockito 可以验证参数是否具有某些属性/字段?

新手上路,请多包涵

说我在嘲笑这个班级 Foo

 class Foo {
  public void doThing(Bar bar) {
    // ...
  }
}

这是 Bar

 class Bar {
  private int i;
  public int getI() { return i; }
  public void setI(int i) { this.i = i; }
}

I know I can use Mockito’s verify functionality to see if Foo#doThing(Bar) was called on the mock with a specific instance of Bar or any Bar with Mockito.any(Bar.class)但有什么方法可以确保它被任何 Bar 调用,但具有特定值 iBar#getI() ?1b—

我所知道的是可能的:

 Foo mockedFoo = mock(Foo.class);
Bar someBar = mock(Bar.class);
...
verify(mockedFoo).doThing(someBar);
verify(mockedFoo).doThing(any(Bar.class);

我想知道的是,是否有一种方法可以验证 Bar 是否作为参数传递了关于它的特定内容。

原文由 Captain Man 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 648
2 个回答

Mockito 2.1.0 及更高版本的 Java 8 中,您可以开箱即用地将 lambda 传递给 argThat, 这样就不需要自定义参数匹配器了。对于 OP 中的示例,将是:

 verify(mockedFoo).doThing(argThat((Bar aBar) -> aBar.getI() == 5));

这是因为从 Mockito 2.1.0 开始, ArgumentMatcher 是一个功能接口。

原文由 Niccolò 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您使用的是 Mockito 2.1.0 或更高版本以及 Java 8 或更高版本,请改为查看 答案,现在更简单了。


我在写问题时找到了答案。

是的你可以。 Instead of using any(Bar.class) you’ll need to implement your own instance of ArgumentMatcher<T> and use Mockito#argThat(Matcher) , for example, say we want to check that i 是 5…

 // in the test (could also be outside)

private static final class BarIs5 extends ArgumentMatcher<Bar> {

  @Override
  public boolean matches(Object argument) {
    return ((Bar) argument).getI() == 5;
  }
}

然后像这样验证: verify(mockedFoo).doThing(argThat(new BarIs5()));


通过添加构造函数参数将其提升一个档次!

 private static final class BarIsWhat extends ArgumentMatcher<Bar> {

  private final int i;

  public BarIsWhat(int i) {
    this.i = i
  }

  @Override
  public boolean matches(Object argument) {
    return ((Bar) argument).getI() == i;
  }
}

然后像这样验证: verify(mockedFoo).doThing(argThat(new BarIsWhat(5)));


更新: 由于有徽章,它出现在我的队列中,并且看到了一些改进的空间。

我试过这个并且有效。您可以使用更简洁的 lambda 表达式(如果您至少不介意未经检查的强制转换警告)。

唯一的问题是 argThat 接受 Hamcrest Matcher不是 @FunctionalInterface 。幸运的是,Mockito 的 ArgumentMatcher 是一个扩展它的抽象类,并且只有一个抽象方法。

在您的测试(或一些常见位置)中创建如下所示的方法

private static <T> ArgumentMatcher<T> matches(Predicate<T> predicate) {
  return new ArgumentMatcher<T>() {

    @SuppressWarnings("unchecked")
    @Override
    public boolean matches(Object argument) {
      return predicate.test((T) argument);
    }
  };
}

现在,在您的测试中,您可以使用 lambda 表达式执行此操作:

 verify(mockedFoo).doThing(argThat(matches( (Bar arg) -> arg.getI() == 5 )));

原文由 Captain Man 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题