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

2022-08-31 11:22:28

说我在嘲笑这门课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; }
}

我知道我可以使用 Mockito 的验证功能来查看是否在 mock 上调用了特定实例或任何带有 ,但是有没有办法确保它被任何 Bar 调用,但具有 iBar#getI() 的特定值?Foo#doThing(Bar)BarBarMockito.any(Bar.class)

我所知道的是可能的:

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

我想知道的是,是否有一种方法可以验证具有特定事物的真实情况是否作为参数传递。Bar


答案 1

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

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

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


答案 2

如果您使用的是Mockito 2.1.0或更高版本以及Java 8或更高版本,请参阅答案,现在它要简单得多。


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

是的,可以。而不是使用你需要实现你自己的ArgumentMatcher<T>实例,并使用Mockito#argThat(Matcher),例如,假设我们要检查它是5...any(Bar.class)i

// 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表达式(至少如果你不介意未经检查的强制转换警告)。

唯一的问题是接受一个不是.幸运的是,Mockito's是一个抽象类,它扩展了它,只有一个抽象方法。argThatMatcher@FunctionalInterfaceArgumentMatcher

在你的测试(或一些常见的位置)做一个如下的方法

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

推荐