Java Mockito Matchers isA、any、eq 和 same 之间有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30890011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between Mockito Matchers isA, any, eq, and same?
提问by Silly Sally
I am confused on what's the difference between them, and which one to choose in which case. Some difference might be obvious, like any
and eq
, but I'm including them all just to be sure.
我对它们之间的区别以及在这种情况下选择哪一个感到困惑。一些差异可能很明显,例如any
和eq
,但我将它们都包括在内是为了确定。
I wonder about their differences because I came across this problem: I have this POST method in a Controller class
我想知道它们的区别,因为我遇到了这个问题:我在 Controller 类中有这个 POST 方法
public Response doSomething(@ResponseBody Request request) {
return someService.doSomething(request);
}
And would like to perform a unit test on that controller. I have two versions. The first one is the simple one, like this
并想对该控制器执行单元测试。我有两个版本。第一个是简单的,像这样
@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));
}
But I wanted to use a MockMvc approach, like this one
但我想使用 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")));
}
Both work well. But I wanted my someServiceMock.doSomething()
in the MockMvc approach to receive req
, or at least an object that has the same variable values as req
(not just any Request
class), and return res
, just like the first. I know that it's impossible using the MockMvc approach (or is it?), because the object passed in the actual call is always different from the object passed in the mock. Is there anyway I can achieve that? Or does it even make sense to do that? Or should I be satisfied using any(Request.class)
? I've tried eq
, same
, but all of them fail.
两者都运作良好。但是我希望我someServiceMock.doSomething()
在 MockMvc 方法中接收req
,或者至少是一个与req
(不仅仅是任何Request
类)具有相同变量值的对象,然后返回res
,就像第一个一样。我知道使用 MockMvc 方法是不可能的(或者是吗?),因为在实际调用中传递的对象总是与在模拟中传递的对象不同。反正我能做到吗?或者这样做是否有意义?或者我应该满意使用any(Request.class)
?我试过eq
,,same
但都失败了。
Thank you in advance. I hope I explained myself well.
先感谢您。我希望我能很好地解释自己。
采纳答案by Jeff Bowman
any()
checks absolutely nothing. In Mockito 1.x,any(T.class)
also checks absolutely nothing but also saves you a cast (prior to Java 8).This is due to change in Mockito 2.0 and beyond, when
any(T.class)
will shareisA
semantics to mean "anyT
" or properly "any instance of typeT
".any()
will still check absolutely nothing.isA(T.class)
checks that the argumentinstanceof T
, implying it is non-null.same(obj)
checks that the argument is the same instance asobj
, such thatarg == obj
is true.eq(obj)
checks that the argument equalsobj
according to itsequals
method. This is also the behavior if you pass in real values without using matchers.Note that unless
equals
is overridden, you'll see the default Object.equals implementation, which would have the same behavior assame(obj)
.
any()
检查绝对没有。在 Mockito 1.x 中,any(T.class)
也绝对不检查任何内容,但也为您节省了强制转换(Java 8 之前)。这是由于 Mockito 2.0 及更高版本中的更改,何时
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)
.
If you need more exact customization, you can use an adapter for your own predicate:
如果您需要更精确的自定义,您可以为您自己的谓词使用适配器:
- For Mockito 1.x, use
argThat
with a custom HamcrestMatcher<T>
that selects exactly the objects you need. - For Mockito 2.0 and beyond, use
Matchers.argThat
with a customorg.mockito.ArgumentMatcher<T>
, orMockitoHamcrest.argThat
with a custom HamcrestMatcher<T>
.
- 对于 Mockito 1.x,
argThat
与自定义 Hamcrest 一起使用,以Matcher<T>
准确选择您需要的对象。 - 对于 Mockito 2.0 及更高版本,请
Matchers.argThat
与自定义org.mockito.ArgumentMatcher<T>
或MockitoHamcrest.argThat
自定义 Hamcrest 一起使用Matcher<T>
。
回答by Alex Pruss
If your Request.class implements equals, then you can use eq():
如果你的 Request.class 实现了 equals,那么你可以使用 eq():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
The above whenwould activate on
上面什么时候会激活
fooService.fooFxn(otherBar);
if
如果
otherBar.equals(bar);
Alternatively, if you want to the mock to work for some other subset of input (for instance, all Bars with Bar.getBarLength()>10), you could create a Matcher. I don't see this pattern too often, so usually I create the Matcher as a private class:
或者,如果您想让模拟用于输入的其他一些子集(例如,所有 Bars with Bar.getBarLength()>10),您可以创建一个匹配器。我不经常看到这种模式,所以通常我将 Matcher 创建为私有类:
private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
public boolean matches(Object otherBar){
//Checks, casts, etc.
return otherBar.getBarLength()>10;
}
}
You would then use this matcher as follows:
然后,您将按如下方式使用此匹配器:
when(fooService.fooFxn(argThat(new BarMatcher())).then...
Hope that helps!
希望有帮助!