test method example ejemplo java unit-testing mockito difference matcher

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ántica isA para indicar "cualquier T " o correctamente "cualquier instancia de tipo T ". any() todavía no comprobará absolutamente nada.

  • isA(T.class) verifica que el argumento instanceof T , lo que implica que no es nulo.

  • same(obj) verifica que el argumento sea la misma instancia que obj , de modo que arg == obj sea ​​verdadero.

  • eq(obj) verifica que el argumento sea igual a obj acuerdo con su método equals . Este es también el comportamiento si se pasan valores reales sin usar emparejadores.

    Tenga en cuenta que a menos que se invalide equals a equals , verá la implementación predeterminada Object.equals, que tendría el mismo comportamiento que el same(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 Hamcrest Matcher<T> personalizado Matcher<T> que selecciona exactamente los objetos que necesita.
  • Para Mockito 2.0 y más allá, use Matchers.argThat con un org.mockito.ArgumentMatcher<T> , o MockitoHamcrest.argThat con un Matching Hamcrest personalizado Matcher<T> .