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 eq
aber 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 req
oder 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
, same
aber alle scheitern.
-
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 T
was bedeutet, dass es nicht null ist.
-
same(obj)
überprüft, ob sich das Argument auf dieselbe Instanz wie bezieht obj
so 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 refEq
die 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 refEq
und wie in dieser Ausgabe, die Sie vielleicht bevorzugen eq
um Ihren Klassen eine bessere Kapselung ihres Gleichheitsgefühls zu geben.
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!