java - example - mockito spring
Mockito. Verificar los argumentos del método (8)
He buscado en Google sobre esto, pero no encontré nada relevante. Tengo algo como esto:
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, quiero verificar que mymethod(Object o)
, que se llama inside runtestmethod()
, se llamó con el Object o
, no con cualquier otro. Pero siempre paso la prueba, sea lo que sea que puse 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")));
Yo siempre paso la prueba. ¿Cómo puedo lograr esa verificación (si es posible)?
Gracias.
¿Estás tratando de hacer la igualdad lógica utilizando el método .equals del objeto? Puedes hacer esto utilizando el parche argThat que está incluido en Mockito
import static org.mockito.Matchers.argThat
A continuación, puede implementar su propio argumento de argumento que diferirá 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 usando tu código puedes actualizarlo para 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 solo busca la igualdad EXACTA (el mismo objeto en la memoria), simplemente haga
verify(mock).mymethod(obj);
Esto verificará que se llamó una vez.
¿Has comprobado el método de iguales para la clase de burla? 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.
¿Lo has probado con el mismo () matcher? Como en:
verify(mockObj).someMethod(same(specificInstance));
Yo 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.
El otro método es usar el método org.mockito.internal.matchers.Equals.Equals en lugar de redefinir uno:
verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));
He usado 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
}
}
También puede usar 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());
}
};
}
Luego verifica esa invocación:
Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
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 usando la anotación @Captor :
@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
//...
verify(mock).doSomething(captor.capture());
assertEquals("John", captor.getValue().getName());
}
- No necesita el
eq
matcher si no usa otras combinaciones. - No está utilizando la sintaxis correcta: su llamada al método debe estar fuera de
.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.
Tu código debería verse así:
Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");