web-dev-qa-db-fra.com

Comment vérifier plusieurs appels de méthode avec différents paramètres

Je souhaite vérifier le comportement de la méthode suivante

public void methodToTest( Exception e, ActionErrors errors ) {

    ...
        errors.add( "exception.message", 
                    ActionMessageFactory.createErrorMessage(e.toString() ));

        errors.add( "exception.detail",
                    ActionMessageFactory.createErrorMessage(e.getStackTrace()[0].toString() ));

    ...
}

Dans ma classe @Test, j'espérais faire quelque chose comme ceci pour vérifier que errors.add() est appelé avec "exception.message" et à nouveau avec "exception.detail".

verify(errors).add(eq("exception.message"), any(ActionError.class));
verify(errors).add(eq("exception.detail"), any(ActionError.class));

cependant Mockito se plaint comme suit

Argument(s) are different! Wanted:
actionErrors.add(
    "exception.message",
    <any>
);

Actual invocation has different arguments:
actionErrors.add(
    "exception.detail",
    org.Apache.struts.action.ActionError@38063806
);

Comment puis-je dire à Mockito de vérifier les deux valeurs?

96
Brad

Des lectures supplémentaires m'ont amené à essayer d'utiliser ArgumentCaptors et les travaux suivants, bien que beaucoup plus verbeux que je le voudrais.

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);

verify(errors, atLeastOnce()).add(argument.capture(), any(ActionMessage.class));

List<String> values = argument.getAllValues();

assertTrue(values.contains("exception.message"));
assertTrue(values.contains("exception.detail"));
95
Brad

Si l'ordre des deux appels add() est pertinent, vous pouvez utiliser InOrder:

InOrder inOrder = inOrder(errors, errors);
inOrder.verify(errors).add(eq("exception.message"), any(ActionError.class));
inOrder.verify(errors).add(eq("exception.detail"), any(ActionError.class));
50
Christoph Walesch

Essayez quelque chose comme ça:

verify(errors, times(2))
     .add(AdditionalMatchers.or(eq("exception.message"), eq("exception.detail")),
          any(ActionError.class));
23
John B

vous avez probablement un problème dans votre code. En fait, vous écrivez ce code:

Map<Character, String> map = mock(Map.class);

map.put('a', "a");
map.put('b', "b");
map.put('c', "c");

verify(map).put(eq('c'), anyString());
verify(map).put(eq('a'), anyString());
verify(map).put(eq('b'), anyString());

Notez que la première vérification n'est même pas en ordre en ce qui concerne les invocations réelles.

De plus, je vous recommanderais de ne pas vous moquer de types que vous ne possédez pas, par exemple le type struts.

[EDIT @Brad]

Après avoir exécuté le code de Brice (ci-dessus) dans mon IDE), je constate que j'ai utilisé ActionError au lieu d'ActionMessage, c'est pourquoi ma verify () ne correspondait pas. me trompant en me faisant croire que c’était le premier argument qui ne correspondait pas.

Donc, la réponse à ma question est

/** 
 * note that ActionMessageFactory.createErrorMessage() returns ActionMessage
 * and ActionError extends ActionMessage
 */
verify(errors).add(eq("exception.message"), any(ActionMessage.class));
verify(errors).add(eq("exception.detail"), any(ActionMessage.class));
16
Brice

Vous pouvez utiliser Mockito.atLeastOnce() qui permet à Mockito de réussir le test même si cet objet mockObject sera appelé plusieurs fois.

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(2));
8
sendon1982

De manière similaire à @ sendon1928, nous pouvons utiliser:

Mockito.times(wantedInvocationCount)

pour être sûr que la méthode s'appelle le nombre exact de fois (solution préférable à mon avis). Ensuite, nous pouvons appeler

Mockito.verifyNoMoreInteractions(mock)

Pour s'assurer que cette maquette n'était plus utilisée dans aucun contexte. Exemple complet:

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(2));

Mockito.verifyNoMoreInteractions(mockObject)
0
Michał Powłoka