314 votes

Vérifier la valeur d'un attribut d'objet avec mockito

J'ai un appel de méthode que je veux simuler avec mockito. Pour commencer, j'ai créé et injecté une instance d'un objet sur lequel la méthode sera appelée. Mon but est de vérifier l'un des objets dans l'appel de la méthode.

Y a-t-il un moyen pour que mockito vous permette d'affirmer ou de vérifier l'objet et ses attributs lorsque la méthode mock est appelée ?

exemple

Mockito.verify(mockedObject)
       .someMethodOnMockedObject(
              Mockito.<SomeObjectAsArgument>anyObject())

Au lieu de faire anyObject() Je veux vérifier que l'objet argument contient certains champs particuliers.

Mockito.verify(mockedObject)
       .someMethodOnMockedObject(
              Mockito.<SomeObjectAsArgument>**compareWithThisObject()**)

0 votes

Comme alternative à l'utilisation de mockito dans ces cas, vous pouvez envisager de créer un stub personnalisé qui étend la classe du mockedObject, et surcharge someMethodOnMockedObject pour sauvegarder l'objet pour une comparaison ultérieure.

629voto

iraSenthil Points 1966

Une nouvelle fonctionnalité ajoutée à Mockito rend cela encore plus facile,

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

Jetez un coup d'oeil à Mockito documentation


Dans le cas où il y a plus d'un paramètre, et que la capture d'un seul paramètre est souhaitée, utilisez d'autres ArgumentMatchers pour envelopper le reste des arguments :

verify(mock).doSomething(eq(someValue), eq(someOtherValue), argument.capture());
assertEquals("John", argument.getValue().getName());

2 votes

si votre méthode a plus d'un argument, vous devez utiliser des Matchers pour tous les autres arguments également. akcasoy.wordpress.com/tag/argumentcaptor

1 votes

Que faire s'il y a plusieurs arguments ? Comment spécifier celui qui vous intéresse exactement ?

2 votes

@IgorGanapolsky En supposant qu'il y ait un deuxième paramètre String pour doSomething, vous devez faire : verify(mock).doSomething(argument.capture(), anyString()) ;

76voto

John29 Points 285

Je pense que la manière la plus simple de vérifier un objet d'argument est d'utiliser la fonction refEq méthode :

Mockito.verify(mockedObject).someMethodOnMockedObject(ArgumentMatchers.refEq(objectToCompareWith));

Il peut être utilisé même si l'objet n'implémente pas l'option equals() parce que la réflexion est utilisée. Si vous ne voulez pas comparer certains champs, il suffit d'ajouter leurs noms comme arguments de la commande refEq .

1 votes

c'est une manière très élégante mais malheureusement org.mockito.Matchers est maintenant déprécié

9 votes

@ihebiheb Il a été déplacé vers ArgumentMatchers.

54voto

charleyc Points 927

Une autre possibilité, si vous ne voulez pas utiliser l'option ArgumentCaptor (par exemple, parce que vous utilisez également le stubbing), est d'utiliser Hamcrest Matchers en combinaison avec Mockito.

import org.mockito.Mockito
import org.hamcrest.Matchers
...

Mockito.verify(mockedObject).someMethodOnMockedObject(MockitoHamcrest.argThat(
    Matchers.<SomeObjectAsArgument>hasProperty("propertyName", desiredValue)));

5 votes

Sidenote : assurez-vous que le Matchers est correct, car l'écriture de la même ligne de code avec le package org.mockito.Matchers lance une exception trompeuse indiquant que le paramètre de la fonction fantaisie ne correspond tout simplement pas.

5 votes

Veuillez noter que dans les versions modernes de Mockito, il est MockitoHamcrest.argThat() et non Mockito.argThat()

20voto

Walery Strauch Points 1315

Cette réponse est basée sur réponse de iraSenthil mais avec une annotation ( Capteur ). À mon avis, elle présente certains avantages :

  • c'est plus court
  • il est plus facile à lire
  • il peut gérer les génériques sans avertissement

Exemple :

@RunWith(MockitoJUnitRunner.class)
public class SomeTest{

    @Captor
    private ArgumentCaptor<List<SomeType>> captor;

    //...

    @Test 
    public void shouldTestArgsVals() {
        //...
        verify(mockedObject).someMethodOnMockedObject(captor.capture());

        assertThat(captor.getValue().getXXX(), is("expected"));
    }
}

11voto

GuiSim Points 661

Si vous utilisez Java 8, vous pouvez utiliser des expressions lambda pour établir des correspondances.

import java.util.Optional;
import java.util.function.Predicate;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;

public class LambdaMatcher<T> extends BaseMatcher<T>
{
    private final Predicate<T> matcher;
    private final Optional<String> description;

    public LambdaMatcher(Predicate<T> matcher)
    {
        this(matcher, null);
    }

    public LambdaMatcher(Predicate<T> matcher, String description)
    {
        this.matcher = matcher;
        this.description = Optional.ofNullable(description);
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean matches(Object argument)
    {
        return matcher.test((T) argument);
    }

    @Override
    public void describeTo(Description description)
    {
        this.description.ifPresent(description::appendText);
    }
}

Exemple d'appel

@Test
public void canFindEmployee()
{
    Employee employee = new Employee("John");
    company.addEmployee(employee);

    verify(mockedDal).registerEmployee(argThat(new LambdaMatcher<>(e -> e.getName()
                                                                         .equals(employee.getName()))));
}

Plus d'informations : http://source.coveo.com/2014/10/01/java8-mockito/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X