web-dev-qa-db-fra.com

Mockito. Vérifier les arguments de la méthode

J'ai googlé à ce sujet, mais je n'ai rien trouvé de pertinent. J'ai quelque chose comme ça:

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

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

Maintenant, je veux vérifier que mymethod(Object o), qui est appelée à l'intérieur de runtestmethod(), a été appelée avec Object o, pas un autre. Mais je passe toujours le test, quoi que je mette sur la vérification, par exemple avec:

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

ou

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

ou

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

Je passe toujours le test. Comment puis-je effectuer cette vérification (si possible)?

Je vous remercie.

180
manolowar

Une alternative à ArgumentMatcher est ArgumentCaptor .

Exemple officiel:

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

Un capteur peut également être défini à l'aide de l'annotation @ Captor :

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

Essayez-vous de faire une égalité logique en utilisant la méthode .equals de l'objet? Vous pouvez le faire en utilisant le matcher argThat inclus dans Mockito

import static org.mockito.Matchers.argThat

Ensuite, vous pouvez implémenter votre propre correcteur d'arguments qui sera appliqué à chaque objet. Méthode .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);
    }
}

Maintenant, en utilisant votre code, vous pouvez le mettre à jour pour lire ...

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 vous vous contentez d'égalité EXACT (même objet en mémoire), il suffit de faire

verify(mock).mymethod(obj);

Cela vérifiera qu'il a été appelé une fois.

58
Matthew Kirkley
  • Vous n'avez pas besoin du matcher eq si vous n'utilisez pas d'autres correspondants.
  • Vous n'utilisez pas la syntaxe correcte - votre appel de méthode doit être en dehors de .verify(mock). Vous lancez maintenant la vérification sur le résultat de l'appel de méthode, sans rien vérifier (ne pas effectuer d'appel de méthode). Par conséquent, tous les tests sont réussis.

Votre code devrait ressembler à:

Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");
47
Bozho

J'ai utilisé Mockito.verify de cette façon

@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
    }
}
6
Free-Minded

L'autre méthode consiste à utiliser la méthode org.mockito.internal.matchers.Equals.Equals au lieu d'en redéfinir une:

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));
4
Nils Renaud

Avez-vous vérifié la méthode equals pour la classe mockable? Si celui-ci retourne toujours true ou si vous testez la même instance sur la même instance et que la méthode equal n'est pas écrasée (et ne vérifie donc que les références), elle renvoie true.

4
rit

voici comment vous pouvez échouer votre vérification d'argument:

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

    ...
    verify(mock).mymethod(argThat(
                                  (x)->false
                                 ));
2
epox

Avez-vous essayé avec le même () matcher? Un péché:

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

J'ai eu le même problème. Je l'ai essayé avec le matcher eq () ainsi que le matcher refEq () mais j'ai toujours eu des faux positifs. Lorsque j'ai utilisé le même matcher (), le test a échoué lorsque les arguments étaient des instances différentes et passé une fois, les arguments étaient la même instance.

1
cbbcloud