Mockito Matchers isA、any、eq 和 same 有什么区别?
我对它们之间的区别以及在哪种情况下选择哪个感到困惑.有些区别可能很明显,例如 any
和 eq
,但我将它们都包括在内只是为了确定.
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.
我想知道它们的区别,因为我遇到了这个问题:我在 Controller 类中有这个 POST 方法
I wonder about their differences because I came across this problem: I have this POST method in a Controller class
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));
}
但我想使用 MockMvc 方法,比如这个
But I wanted to use a MockMvc approach, like this one
@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")));
}
两者都运作良好.但我希望我的 someServiceMock.doSomething()
在 MockMvc 方法中接收 req
,或者至少是一个与 req
(不仅仅是任何 Request
类),并返回 res
,就像第一个一样.我知道使用 MockMvc 方法是不可能的(或者是吗?),因为在实际调用中传递的对象总是与在模拟中传递的对象不同.无论如何我可以做到这一点吗?或者这样做是否有意义?或者我应该对使用 any(Request.class)
感到满意吗?我试过eq
,same
,但都失败了.
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.
推荐答案
any()
绝对不检查任何内容.从 Mockito 2.0 开始,any(T.class)
共享isA
语义以表示任何T
";或正确地T
类型的任何实例".any()
checks absolutely nothing. Since Mockito 2.0,any(T.class)
sharesisA
semantics to mean "anyT
" or properly "any instance of typeT
".这是与 Mockito 1.x 相比的一个变化,其中
any(T.class)
完全没有检查但在 Java 8 之前保存了一个强制转换:任何类型的对象,对于给定的类不是必需的.提供类参数只是为了避免强制转换."This is a change compared to Mockito 1.x, where
any(T.class)
checked absolutely nothing but saved a cast prior to Java 8: "Any kind object, not necessary of the given class. The class argument is provided only to avoid casting."isA(T.class)
检查参数instanceof T
是否为非空.same(obj)
检查参数是否引用与obj
相同的实例,使得arg == obj
为真.same(obj)
checks that the argument refers to the same instance asobj
, such thatarg == obj
is true.eq(obj)
根据其equals
方法检查参数是否等于obj
.如果您在不使用匹配器的情况下传递实际值,这也是这种行为.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.请注意,除非
equals
被覆盖,否则您将看到默认的 Object.equals 实现,其行为与same(obj)
相同.Note that unless
equals
is overridden, you'll see the default Object.equals implementation, which would have the same behavior assame(obj)
.如果您需要更精确的自定义,您可以为自己的谓词使用适配器:
If you need more exact customization, you can use an adapter for your own predicate:
- 对于 Mockito 1.x,请使用
argThat
带有自定义 HamcrestMatcher
,可以准确选择您需要的对象. - 对于 Mockito 2.0 及更高版本,请使用
Matchers.argThat
与自定义org.mockito.ArgumentMatcher
或MockitoHamcrest.argThat
使用自定义 HamcrestMatcher<T>
.
- 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>
.
您也可以使用
refEq
,它使用reflection来确认对象相等;Hamcrest 与公共 bean 的 SamePropertyValuesAs 有类似的实现-样式属性.请注意,在 GitHub issue #1800 上建议弃用和删除refEq
,并且在那个问题中,您可能更喜欢eq
来更好地为您的类提供更好的封装,而不是它们的平等感.You may also use
refEq
, which uses reflection to confirm object equality; Hamcrest has a similar implementation with SamePropertyValuesAs for public bean-style properties. Note that on GitHub issue #1800 proposes deprecating and removingrefEq
, and as in that issue you might prefereq
to better give your classes better encapsulation over their sense of equality.- 对于 Mockito 1.x,请使用
相关文章