簡體   English   中英

Mockito Matchers isA、any、eq 和 same 之間有什么區別?

[英]What's the difference between Mockito Matchers isA, any, eq, and same?

我對它們之間的區別以及在這種情況下選擇哪個感到困惑。 某些差異可能很明顯,例如anyeq ,但為了確定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)感到滿意嗎? 我試過eqsame ,但都失敗了。

  • 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)

如果您需要更精確的自定義,您可以為您自己的謂詞使用適配器:

  • 對於 Mockito 1.x,將argThat與自定義 Hamcrest Matcher<T>一起使用,該Matcher<T>可以准確選擇您需要的對象。
  • 為2.0的Mockito及以后,使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM