Mockito Matchers之间有什么区别是A,any,eq和同样的?

时间:2015-06-17 11:18:07

标签: java unit-testing mockito difference matcher

我很困惑他们之间有什么区别,在哪种情况下选择哪一个。一些差异可能很明显,例如anyeq,但我将它们包括在内只是为了确定。

我想知道他们之间的差异,因为我遇到了这个问题: 我在Controller类中有这个POST方法

public Response doSomething(@ResponseBody Request request) {
    return someService.doSomething(request);
}

并希望在该控制器上执行单元测试。 我有两个版本。第一个是简单的,就像这个

@Test
public void testDoSomething() {
    //initialize ObjectMapper mapper
    //initialize Request req and Response res

    when(someServiceMock.doSomething(req)).thenReturn(res);

    Response actualRes = someController.doSomething(req);
    assertThat(actualRes, is(res));
}

但我想使用MockMvc方法,就像这个

@Test
public void testDoSomething() {
    //initialize ObjectMapper mapper
    //initialize Request req and Response res

    when(someServiceMock.doSomething(any(Request.class))).thenReturn(res);

    mockMvc.perform(post("/do/something")
            .contentType(MediaType.APPLICATION_JSON)
            .content(mapper.writeValueAsString(req))
    )
            .andExpect(status().isOk())
            .andExpect(jsonPath("$message", is("done")));
}

两者都运作良好。但是我希望MockMvc方法中的someServiceMock.doSomething()接收req,或者至少是一个与req具有相同变量值的对象(不仅仅是Request类),并返回res,就像第一个一样。我知道使用MockMvc方法是不可能的(或者是吗?),因为实际调用中传递的对象总是与mock中传递的对象不同。无论如何我能做到吗?或者这样做甚至有意义吗?或者我应该使用any(Request.class)满意吗?我已经尝试了eqsame,但所有这些都失败了。

提前谢谢你。 我希望我能很好地解释自己。

2 个答案:

答案 0 :(得分:60)

  • any()绝不会检查任何内容。在Mockito 1.x中,any(T.class)也绝不会检查任何内容,但也会为你节省一个演员(在Java 8之前)。

    This is due to change in Mockito 2.0 and beyond,当any(T.class)分享isA语义以表示“任何T”或正确“任何类型T的实例”时。 any()仍然会检查一切。

  • isA(T.class)检查参数instanceof T,暗示它是非空的。

  • same(obj)检查参数是否与obj相同,以便arg == obj为真。

  • eq(obj)根据obj方法检查参数是否等于equals。如果您在不使用匹配器的情况下传递实际值,这也是一种行为。

    请注意,除非重写equals,否则您将看到默认的Object.equals实现,其行为与same(obj)相同。

如果您需要更精确的自定义,可以使用适配器作为您自己的谓词:

  • 对于Mockito 1.x,请使用argThat与自定义Hamcrest Matcher<T>一起选择您需要的对象。
  • 对于Mockito 2.0及更高版本,请将Matchers.argThat与自定义org.mockito.ArgumentMatcher<T>一起使用,或将MockitoHamcrest.argThat与自定义Hamcrest Matcher<T>一起使用。

答案 1 :(得分:2)

如果您的Request.class实现了equals,那么您可以使用eq():

Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...

当在

上激活时,上面的
fooService.fooFxn(otherBar);

如果

otherBar.equals(bar);

或者,如果您希望模拟适用于其他输入子集(例如,所有使用Bar.getBarLength()&gt; 10的条形图),则可以创建匹配器。我不经常看到这种模式,所以通常我将Matcher创建为私人类:

private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
  public boolean matches(Object otherBar){
     //Checks, casts, etc.
     return otherBar.getBarLength()>10;
  }
}

然后您将按如下方式使用此匹配器:

when(fooService.fooFxn(argThat(new BarMatcher())).then...

希望有所帮助!