Jaka jest różnica między Mockito Matchers isA, any, eq i same?
Jestem zdezorientowany, jaka jest różnica między nimi, i który z nich wybrać w jakim przypadku. Niektóre różnice mogą być oczywiste, jak any
i eq
, ale włączam je wszystkie dla pewności.
Zastanawiam się nad ich różnicami, ponieważ natknąłem się na ten problem: Mam tę metodę POST w klasie kontrolera
public Response doSomething(@ResponseBody Request request) {
return someService.doSomething(request);
}
I chciałby przeprowadzić test jednostkowy na tym kontrolerze. Mam dwie wersje. Pierwszy jest prosty, jak to
@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));
}
Ale chciałem użyć metody MockMvc, takiej jak ta
@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")));
}
Oba działają dobrze. Ale chciałem, aby moja someServiceMock.doSomething()
w podejściu MockMvc otrzymała req
, lub przynajmniej obiekt, który ma takie same wartości zmiennych jak req
(nie byle jaką Request
klasę), i zwróciła res
, tak jak pierwsza. Wiem, że to niemożliwe przy użyciu podejścia MockMvc (a może jest?), ponieważ obiekt przekazany w rzeczywistym wywołaniu zawsze różni się od obiektu przekazanego w makiecie. Czy w ogóle mogę osiągnąć? Czy to ma sens? Czy powinienem być usatysfakcjonowany używając any(Request.class)
? Próbowałem eq
, same
, ale wszystkie zawodzą.
2 answers
-
any()
nic nie sprawdza. W Mockito 1.x,any(T.class)
również nic nie sprawdza, ale również zapisuje Ci obsadę (przed Javą 8).Jest to spowodowane zmianą w Mockito 2.0 i później, kiedy
any(T.class)
będzie dzielić semantykęisA
na "anyT
" lub właściwie "any instance of typeT
".any()
nadal niczego nie sprawdzi. isA(T.class)
sprawdza, czy argumentinstanceof T
, sugerując, że jest inny niż null.same(obj)
kontrole że argument jest tą samą instancją coobj
, tak żearg == obj
jest prawdą.-
eq(obj)
sprawdza, czy argument jest równyobj
zgodnie z jego metodąequals
. Jest to również zachowanie, jeśli przekazujesz prawdziwe wartości bez użycia matcherów.Zauważ, że jeśli
equals
nie zostanie nadpisana, zobaczysz obiekt domyślny.równa się implementacja, która miałaby takie samo zachowanie jaksame(obj)
.
Jeśli potrzebujesz dokładniejszego dostosowania, możesz użyć adaptera do Twoje własne orzeczenie:
- Dla Mockito 1.x, Użyj {[17] } z niestandardowym Hamcrest
Matcher<T>
, który wybiera dokładnie obiekty, których potrzebujesz.
W przypadku Mockito 2.0 i nowszych, użyj
Matchers.argThat
z niestandardowym org.mockito.ArgumentMatcher<T>
lub MockitoHamcrest.argThat
z niestandardowym Hamcrest Matcher<T>
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:42
Jeśli Twoja prośba.klasa implementuje równe, wtedy możesz użyć eq ():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
Powyższe Kiedy uaktywni się na
fooService.fooFxn(otherBar);
If
otherBar.equals(bar);
Alternatywnie, jeśli chcesz, aby makieta działała dla jakiegoś innego podzbioru danych wejściowych (na przykład, wszystkie paski z paskiem.getBarLength ()>10), można utworzyć Matcher. Nie widzę tego wzoru zbyt często, więc zazwyczaj tworzę Matcher jako klasę prywatną: {]}
private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
public boolean matches(Object otherBar){
//Checks, casts, etc.
return otherBar.getBarLength()>10;
}
}
Wtedy użyłbyś tego matchera jako "follows": {]}
when(fooService.fooFxn(argThat(new BarMatcher())).then...
Mam nadzieję, że to pomoże!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 11:55:33