如何使用具有特定属性的参数来存根方法

时间:2016-05-20 11:12:46

标签: java mockito

如何使用具有特定属性的参数来存根方法?

例如:

doReturn(true).when(object).method( 
    // an object that has a property prop1 equals to "myprop1"
    // and prop2 equals to "myprop2"
)

1 个答案:

答案 0 :(得分:1)

你需要一个自定义的Mockito匹配器或Hamcrest匹配器来解决这个问题,或者两者的混合。 The two work a little differently,但您可以将它们与适配器一起使用。

使用Hamcrest

您需要使用Matchers.argThat(Mockito 1.x)或MockitoHamcrest.argThat(Mockito 2.x)来修改Hamcrest hasProperty匹配器并将其合并。

doReturn(true).when(object).method(
  argThat(allOf(hasProperty("prop1", eq("myProp1")),
                hasProperty("prop2", eq("myProp2"))))
)

在这里,argThat调整Hamcrest匹配器在Mockito中工作,allOf确保您只匹配满足这两个条件的对象,hasProperty检查对象,eq (特别是Hamcrest的eq,而不是Mockito的eq)比较字符串相等。

没有Hamcrest

Mockito不再直接依赖于Mockito v2.0的Hamcrest(现在测试版),所以你可能想要以类似的方式与Mockito的ArgumentMatcher类做同样的逻辑。

doReturn(true).when(object).method(
  argThat(new ArgumentMatcher<YourObject>() {
    @Override public boolean matches(Object argument) {
      if (!(argument instanceof YourObject)) {
        return false;
      }
      YourObject yourObject = (YourObject) argument;
      return "myProp1".equals(yourObject.getProp1())
          && "myProp2".equals(yourObject.getProp2());
    }
  })
)

当然,同样的自定义匹配器类技术也适用于Hamcrest,但如果您确定使用的是Hamcrest,则可能更喜欢上面的hasProperty技术。

重构

提醒一句:虽然欢迎您保存Matcher对象(无论是通过静态帮助方法返回还是保存在字段中),但仍然可以调用argThat has side effects,必须在致电method 期间拨打电话。换句话说,如果需要,可以保存并重复使用MatcherArgumentMatcher个实例,但不要重构对argThat的调用,除非你这样做为静态方法< / em>所以argThat仍会在合适的时间被调用。

// GOOD with Hamcrest's Matcher:
Matcher<YourObject> hasTwoProperties = (...)
doReturn(true).when(object).method(argThat(hasTwoProperties));

// GOOD with Mockito's ArgumentMatcher:
ArgumentMatcher<YourObject> hasTwoProperties = (...)
doReturn(true).when(object).method(argThat(hasTwoProperties));

// BAD because argThat is called early:
YourObject expectedObject = argThat(...);
doReturn(true).when(object).method(expectedObject);

// GOOD because argThat is called correctly within the method call:
static YourObject expectedObject() { return argThat(...); }
doReturn(true).when(object).method(expectedObject());