java - method - ¿Cuál es la diferencia entre Mockito Matchers isA, any, eq, y same?
mockito service test example (2)
Estoy confundido sobre cuál es la diferencia entre ellos y cuál elegir en qué caso. Alguna diferencia puede ser obvia, como any
eq
, pero las estoy incluyendo todas para estar seguro.
Me pregunto acerca de sus diferencias porque encontré este problema: tengo este método POST en una clase de Controlador
public Response doSomething(@ResponseBody Request request) {
return someService.doSomething(request);
}
Y me gustaría realizar una prueba de unidad en ese controlador. Tengo dos versiones. El primero es el sencillo, así.
@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));
}
Pero quería usar un enfoque de MockMvc, como este
@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")));
}
Ambos funcionan bien. Pero quise que someServiceMock.doSomething()
en el enfoque de MockMvc recibiera req
, o al menos un objeto que tenga los mismos valores de variable que req
(no cualquier clase de Request
), y devuelva res
, como el primero. Sé que es imposible usar el enfoque de MockMvc (¿o sí?), Porque el objeto pasado en la llamada real siempre es diferente del objeto pasado en el simulacro. ¿Hay de todos modos puedo lograr eso? ¿O incluso tiene sentido hacer eso? ¿O debería estar satisfecho utilizando any(Request.class)
? He intentado eq
, lo same
, pero todos fallan.
Gracias de antemano. Espero que me haya explicado bien.
Si su Request.class implementa igual, entonces puede usar eq ():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
Lo anterior cuando se activaría en
fooService.fooFxn(otherBar);
Si
otherBar.equals(bar);
Alternativamente, si desea que el simulacro funcione para algún otro subconjunto de entrada (por ejemplo, todas las Barras con Bar.getBarLength ()> 10), puede crear un Matcher. No veo este patrón con demasiada frecuencia, así que normalmente creo el Matcher como una clase privada:
private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
public boolean matches(Object otherBar){
//Checks, casts, etc.
return otherBar.getBarLength()>10;
}
}
Entonces usarías este matcher de la siguiente manera:
when(fooService.fooFxn(argThat(new BarMatcher())).then...
¡Espero que ayude!
any()
comprueba absolutamente nada. En Mockito 1.x,any(T.class)
tampoco verifica absolutamente nada, pero también te guarda un lanzamiento (antes de Java 8).Esto se debe a un cambio en Mockito 2.0 y más allá , cuando
any(T.class)
compartirá la semánticaisA
para indicar "cualquierT
" o correctamente "cualquier instancia de tipoT
".any()
todavía no comprobará absolutamente nada.isA(T.class)
verifica que el argumentoinstanceof T
, lo que implica que no es nulo.same(obj)
verifica que el argumento sea la misma instancia queobj
, de modo quearg == obj
sea verdadero.eq(obj)
verifica que el argumento sea igual aobj
acuerdo con su métodoequals
. Este es también el comportamiento si se pasan valores reales sin usar emparejadores.Tenga en cuenta que a menos que se invalide
equals
aequals
, verá la implementación predeterminada Object.equals, que tendría el mismo comportamiento que elsame(obj)
.
Si necesita una personalización más exacta, puede usar un adaptador para su propio predicado:
- Para Mockito 1.x, use
argThat
con un HamcrestMatcher<T>
personalizadoMatcher<T>
que selecciona exactamente los objetos que necesita. - Para Mockito 2.0 y más allá, use
Matchers.argThat
con unorg.mockito.ArgumentMatcher<T>
, oMockitoHamcrest.argThat
con un Matching Hamcrest personalizadoMatcher<T>
.