2015-06-17 19 views
18

Ich bin verwirrt, was ist der Unterschied zwischen ihnen, und welche in welchem ​​Fall zu wählen. Ein gewisser Unterschied könnte offensichtlich sein, wie any und eq, aber ich nehme sie alle nur um sicher zu sein.Was ist der Unterschied zwischen Mockito Matchers isA, any, eq und same?

ich über ihre Unterschiede fragen, weil ich auf diesem Problem kam: Ich habe diese POST-Methode in einer Controller-Klasse

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

Und möchte einen Unit-Test auf diesem Controller auszuführen. Ich habe zwei Versionen. Die erste ist die einfache, wie dieser

@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)); 
} 

Aber ich wollte einen MockMvc Ansatz verwenden, wie dieser

@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"))); 
} 

Beide gut funktionieren. Aber ich wollte meine someServiceMock.doSomething() in der MockMvc Ansatz, req, oder mindestens ein Objekt, das die gleichen Variablen wie req (nicht nur eine Request Klasse), und res, genau wie die erste. Ich weiß, dass es unmöglich ist, den MockMvc-Ansatz zu verwenden (oder?), Weil das Objekt, das im tatsächlichen Aufruf übergeben wird, sich immer von dem im Mock übergebenen Objekt unterscheidet. Kann ich das überhaupt erreichen? Oder macht es überhaupt Sinn, das zu tun? Oder sollte ich mit any(Request.class) zufrieden sein? Ich habe versucht eq, same, aber alle von ihnen scheitern.

Vielen Dank im Voraus. Ich hoffe ich habe mich gut erklärt.

Antwort

40
  • any() überprüft absolut nichts. In Mockito 1.x, any(T.class) überprüft auch absolut nichts, sondern spart Ihnen auch eine Besetzung (vor Java 8).

    This is due to change in Mockito 2.0 and beyond, wenn any(T.class)isA Semantik teilen „jede T“ oder richtig „jede Instanz vom Typ T“ zu bedeuten. any() wird immer noch absolut nichts überprüfen.

  • isA(T.class) prüft, ob das Argument instanceof T, was bedeutet, dass es nicht null ist.

  • same(obj) überprüft, ob das Argument die gleiche Instanz wie obj ist, so dass arg == obj wahr ist.

  • eq(obj) überprüft, ob das Argument obj gemäß seiner equals Methode entspricht. Dies ist auch das Verhalten, wenn Sie echte Werte übergeben, ohne Matcher zu verwenden.

    Beachten Sie, dass, wenn equals überschrieben wird, die Standard-Object.equals-Implementierung angezeigt wird, die dasselbe Verhalten wie same(obj) haben würde.

Wenn Sie genauere Anpassung benötigen, können Sie einen Adapter für Ihr eigenes Prädikat verwenden:

  • Für Mockito 1.x verwenden argThat mit einem benutzerdefinierten hamcrest Matcher<T>, die genau die Objekte auswählt, die Sie benötigen .
  • Verwenden Sie für Mockito 2.0 und darüber hinaus Matchers.argThat mit einem benutzerdefinierten org.mockito.ArgumentMatcher<T> oder MockitoHamcrest.argThat mit einem benutzerdefinierten Hamcrest Matcher<T>.
2

Wenn Ihr Request.class Geräte entspricht, dann können Sie eq() verwenden:

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

Die oben wenn aktivieren würde auf

fooService.fooFxn(otherBar); 

wenn

otherBar.equals(bar); 

Alternativ, wenn Sie das Mock für eine andere Untergruppe von Inpu arbeiten möchten t (z. B. alle Bars mit Bar.getBarLength()> 10), könnten Sie einen Matcher erstellen. Ich sehe dieses Muster nicht zu oft, so in der Regel ich die Matcher als private Klasse zu erstellen:

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

Sie würden dann diese Matcher wie folgt verwenden:

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

Hoffe, das hilft!

Verwandte Themen