[英]What's the difference between Mockito Matchers isA, any, eq, and same?
我對它們之間的區別以及在這種情況下選擇哪個感到困惑。 某些差異可能很明顯,例如any
和eq
,但為了確定eq
,我將它們全部包括在內。
我想知道它們的區別,因為我遇到了這個問題:我在 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 方法是不可能的(或者是嗎?),因為在實際調用中傳遞的對象總是與在模擬中傳遞的對象不同。 反正我能做到嗎? 或者這樣做是否有意義? 或者我應該使用any(Request.class)
感到滿意嗎? 我試過eq
, same
,但都失敗了。
any()
絕對不檢查。 從 Mockito 2.0 開始, any(T.class)
共享isA
語義以表示“任何T
”或正確的“類型T
任何實例”。
與 Mockito 1.x 相比,這是一個變化,其中any(T.class)
在 Java 8 之前完全沒有檢查但保存了一個強制轉換:“任何種類的對象,不是給定類所必需的。提供 class 參數只是為了避免鑄件。”
isA(T.class)
檢查參數instanceof T
,暗示它是非空的。
same(obj)
檢查參數是否引用與obj
相同的實例,以便arg == obj
為真。
eq(obj)
根據它的equals
方法檢查參數是否等於obj
。 如果您在不使用匹配器的情況下傳遞實際值,這也是行為。
請注意,除非覆蓋equals
,否則您將看到默認的 Object.equals 實現,其行為與same(obj)
。
如果您需要更精確的自定義,您可以為您自己的謂詞使用適配器:
argThat
與自定義 Hamcrest Matcher<T>
一起使用,該Matcher<T>
可以准確選擇您需要的對象。Matchers.argThat
與自定義org.mockito.ArgumentMatcher<T>
或MockitoHamcrest.argThat
與自定義Hamcrest Matcher<T>
您也可以使用refEq
,它使用反射來確認對象相等; Hamcrest 對公共 bean 樣式的屬性具有與SamePropertyValuesAs類似的實現。 請注意,在 GitHub問題 #1800 上建議棄用和刪除refEq
,並且在該問題中,您可能更喜歡eq
更好地為您的類提供更好的封裝,而不是它們的平等感。
如果你的 Request.class 實現了 equals,那么你可以使用 eq():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
上面什么時候會激活
fooService.fooFxn(otherBar);
如果
otherBar.equals(bar);
或者,如果您想讓模擬用於輸入的其他一些子集(例如,所有 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;
}
}
然后,您將按如下方式使用此匹配器:
when(fooService.fooFxn(argThat(new BarMatcher())).then...
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.