Was ist der Unterschied zwischen Mockito Matchers isA, any, eq und same?

Lesezeit: 4 Minuten

Benutzer-Avatar
Dumme Sally

Ich bin verwirrt darüber, was der Unterschied zwischen ihnen ist und welche in welchem ​​​​Fall zu wählen ist. Einige Unterschiede könnten offensichtlich sein, wie z any und eqaber ich schließe sie alle ein, nur um sicherzugehen.

Ich wundere mich über ihre Unterschiede, weil ich auf dieses Problem gestoßen bin: Ich habe diese POST-Methode in einer Controller-Klasse

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

Und möchte einen Komponententest auf diesem Controller durchführen. Ich habe zwei Versionen. Der erste ist der 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 wie diesen verwenden

@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 funktionieren gut. Aber ich wollte meine someServiceMock.doSomething() im MockMvc-Ansatz zu empfangen reqoder zumindest ein Objekt, das die gleichen Variablenwerte hat wie req (nicht irgendein Request Klasse) und zurück res, genau wie die erste. Ich weiß, dass es unmöglich ist, den MockMvc-Ansatz zu verwenden (oder doch?), da sich das im eigentlichen Aufruf übergebene Objekt immer von dem im Mock übergebenen Objekt unterscheidet. Kann ich das irgendwie erreichen? Oder macht es überhaupt Sinn, das zu tun? Oder sollte ich mit der Verwendung zufrieden sein any(Request.class)? ich habe es versucht eq, sameaber alle scheitern.

Benutzer-Avatar
Jeff Bowmann

  • any() überprüft absolut nichts. Seit Mockito 2.0, any(T.class) Anteile isA Semantik bedeutet „beliebig T” oder richtig “jede Instanz des Typs T“.

    Dies ist eine Änderung im Vergleich zu Mockito 1.x, wo any(T.class) absolut nichts überprüft, aber eine Umwandlung vor Java 8 gespeichert: “Jedes Art Objekt, nicht notwendig für die angegebene Klasse. Das Klassenargument wird nur bereitgestellt, um eine Umwandlung zu vermeiden.”

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

  • same(obj) überprüft, ob sich das Argument auf dieselbe Instanz wie bezieht objso dass arg == obj ist wahr.

  • eq(obj) prüft, ob das Argument gleich ist obj nach seiner equals Methode. Dies ist auch das Verhalten, wenn Sie reale Werte ohne Verwendung von Matchern übergeben.

    Beachten Sie, dass es sei denn equals überschrieben wird, sehen Sie die standardmäßige Object.equals-Implementierung, die das gleiche Verhalten wie hätte same(obj).

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

  • Verwenden Sie für Mockito 1.x 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 höher Matchers.argThat mit Brauch org.mockito.ArgumentMatcher<T>oder MockitoHamcrest.argThat mit einem benutzerdefinierten Hamcrest Matcher<T>.

Sie können auch verwenden refEqdie verwendet Betrachtung Objektgleichheit zu bestätigen; Hamcrest hat eine ähnliche Implementierung mit SamePropertyValuesAs für öffentliche Eigenschaften im Bean-Stil. Beachten Sie das auf GitHub Ausgabe Nr. 1800 schlägt vor, veraltet zu sein und zu entfernen refEqund wie in dieser Ausgabe, die Sie vielleicht bevorzugen eq um Ihren Klassen eine bessere Kapselung ihres Gleichheitsgefühls zu geben.

  • Dies ist eine praktische Antwort: nicht nur die Differenzierung von Mockitos 4 Argument Matcher sondern auch angedeutet Risiken mit equals und Anpassung mit argThat 👍

    – hc_dev

    30. Januar 2021 um 11:33 Uhr

  • Bitte hinzufügen refEq() Dieser Matcher kann verwendet werden, wenn equals() für verglichene Objekte nicht implementiert ist. Matcher verwendet die Java-Reflection-API, um die Felder des gewünschten und des tatsächlichen Objekts zu vergleichen.

    – Iwan

    19. Mai 2021 um 9:52 Uhr

  • @Ivan Obwohl es nicht in der ursprünglichen Frage enthalten war, habe ich eine Erwähnung hinzugefügt refEqeinschließlich den Vorschlag, es zu verwerfen und aus Mockito zu entfernen.

    – Jeff Bowmann

    19. Mai 2021 um 20:03 Uhr

  • Was sollten wir also für die neueste Version verwenden?

    – Jack

    16. November 2021 um 6:02 Uhr

  • @Robert Die obige Liste zeigt Ihnen den semantischen Unterschied zwischen ihnen. Sie müssen sie an Ihren Anwendungsfall anpassen.

    – Jeff Bowmann

    16. November 2021 um 6:05 Uhr


Wenn Ihre Request.class equals implementiert, können Sie eq() verwenden:

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

Obenstehendes Wenn würde einschalten

fooService.fooFxn(otherBar);

wenn

otherBar.equals(bar);

Wenn Sie alternativ möchten, dass der Mock für eine andere Teilmenge der Eingabe funktioniert (z. B. alle Bars mit Bar.getBarLength()>10), können Sie einen Matcher erstellen. Ich sehe dieses Muster nicht allzu oft, also erstelle ich den Matcher normalerweise als private Klasse:

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 diesen Matcher dann wie folgt verwenden:

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

Ich hoffe, das hilft!

1053930cookie-checkWas ist der Unterschied zwischen Mockito Matchers isA, any, eq und same?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy