2010-08-24 18 views
108

He buscado en Google sobre esto, pero no encontré nada relevante. Tengo algo como esto:Mockito. Verificar los argumentos del método

Object obj = getObject(); 
Mockeable mock= Mockito.mock(Mockeable.class); 
Mockito.when(mock.mymethod(obj)).thenReturn(null); 

Testeable obj = new Testeable(); 
obj.setMockeable(mock); 
command.runtestmethod(); 

Ahora, yo quiero para verificar que mymethod(Object o), que se llama el interior runtestmethod(), llamaron con el objeto o, no cualquier otra. Pero siempre que pase la prueba, lo pongo en la verificación, por ejemplo, con:

Mockito.verify(mock.mymethod(Mockito.eq(obj))); 

o

Mockito.verify(mock.mymethod(Mockito.eq(null))); 

o

Mockito.verify(mock.mymethod(Mockito.eq("something_else"))); 

Siempre pasa la prueba. ¿Cómo puedo lograr esa verificación (si es posible)?

Gracias.

Respuesta

40
  • No necesita el emparejador eq si no utiliza otros mezcladores.
  • No está utilizando la sintaxis correcta; la llamada a su método debe realizarse fuera del .verify(mock). Ahora está iniciando la verificación del resultado de la llamada al método, sin verificar nada (no realizando una llamada a un método). Por lo tanto, todas las pruebas están pasando.

código debe ser similar:

Mockito.verify(mock).mymethod(obj); 
Mockito.verify(mock).mymethod(null); 
Mockito.verify(mock).mymethod("something_else"); 
+0

Lo había intentado antes, y nuevamente ahora para estar seguro. Todavía tengo el mismo problema, la prueba siempre pasa. – manolowar

+1

, entonces quizás no muestre lo suficiente. Esto debería funcionar. – Bozho

3

¿Ha comprobado el método equals de la clase mockable? Si este devuelve siempre verdadero o si prueba la misma instancia contra la misma instancia y el método igual no se sobrescribe (y por lo tanto solo verifica con las referencias), entonces devuelve verdadero.

48

¿Está tratando de hacer la igualdad lógica utilizando el método .equals del objeto? Para ello, puede utilizar la matcher argThat que se incluye en Mockito

import static org.mockito.Matchers.argThat 

A continuación se puede implementar su propio matcher argumento de que aplazará a cada método de objetos .equals

private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> { 
    T thisObject; 

    public ObjectEqualityArgumentMatcher(T thisObject) { 
     this.thisObject = thisObject; 
    } 

    @Override 
    public boolean matches(Object argument) { 
     return thisObject.equals(argument); 
    } 
} 

Ahora, utilizando el código que pueda actualizarlo a leer ...

Object obj = getObject(); 
Mockeable mock= Mockito.mock(Mockeable.class); 
Mockito.when(mock.mymethod(obj)).thenReturn(null); 

Testeable obj = new Testeable(); 
obj.setMockeable(mock); 
command.runtestmethod(); 

verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj))); 

Si sólo se va para la igualdad exacta (el mismo objeto en la memoria), acaba de hacer

verify(mock).mymethod(obj); 

Esto verificará que se llamó una vez.

+1

Puede usar la compilación en la clase 'ReflectionEquals' para esos fines. – takacsot

+2

+1 por tu respuesta. Pero me gustaría añadir que 'verify (mock) .mymethod (obj);' no verifica la igualdad EXACTA (el mismo objeto en la memoria). En su lugar, utiliza los objetos iguales-método que podrían haber sido ignorados. – efux

+0

También puede crear una implementación anónima de 'ArgumentMatcher' para que sea menos detallada. – botchniaque

1

¿Has probado con el mismo() matcher? Como en:

verify(mockObj).someMethod(same(specificInstance)); 

Tuve el mismo problema. Lo intenté con el eq() matcher y con el refEq() matcher, pero siempre tuve falsos positivos. Cuando utilicé el mismo() matcher, la prueba falló cuando los argumentos eran instancias diferentes y pasaron una vez que los argumentos eran la misma instancia.

140

Una alternativa a ArgumentMatcher es ArgumentCaptor.

ejemplo Oficial:

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class); 
verify(mock).doSomething(argument.capture()); 
assertEquals("John", argument.getValue().getName()); 

Un captor también se puede definir mediante el @Captor anotación:

@Captor ArgumentCaptor<Person> captor; 
//... MockitoAnnotations.initMocks(this); 
@Test public void test() { 
    //... 
    verify(mock).doSomething(captor.capture()); 
    assertEquals("John", captor.getValue().getName()); 
} 
+0

¡Gracias por la muestra! Nunca lo usé Se siente un poco raro tener cosas como * captor * en el código, pero me ayudó. – Artemis

+0

Jaja, no entendí la pregunta, pero la respuesta me ayudó mucho. Gracias :-) –

+0

Importante: Llamada verify()/capture() _after_ usando el simulacro. Estaba pensando que tenía que ser "instalado" antes ... –

-1

También puede utilizar TypeSafeDiagnosingMatcher

private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) { 
    return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() { 

     StringBuilder text = new StringBuilder(500); 

     @Override 
     protected boolean matchesSafely(GetPackagesRequest req, Description desc) { 
      String productCode = req.getPackageIds().iterator().next().getValue(); 
      if (productCode.equals(request.getSupplierProductCode())) { 
       text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode()); 
       return true; 
      } 

      text.append(req.toString()); 
      return false; 
     } 

     @Override 
     public void describeTo(Description d) { 
      d.appendText(text.toString()); 
     } 
    }; 
} 

A continuación, compruebe que la invocación:

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request))); 
2

El otro método es utilizar el método org.mockito.internal.matchers.Equals.Equals en lugar de la redefinición de una:

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted))); 
0

he utilizado Mockito.verify de esta manera

@UnitTest 
public class JUnitServiceTest 
{ 
    @Mock 
    private MyCustomService myCustomService; 


    @Test 
    public void testVerifyMethod() 
    { 
     Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0)) 
     Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times 
     Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time 
     Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times 
     Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times 
     Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); // no other method called except this 
    } 
} 
Cuestiones relacionadas