web-dev-qa-db-fra.com

Mock même méthode avec des paramètres différents

J'utilise mockito pour tester mon service métier et utilise un utilitaire que je veux me moquer. il y a au moins 2-3 appels dans chaque méthode de service pour l'utilitaire avec des arguments différents. 

Existe-t-il un moyen recommandé d'utiliser plusieurs when(...).thenReturn(...) pour la même méthode mais pour des arguments différents?

Je veux aussi utiliser any() marcher aussi à l'intérieur. C'est possible?

Mise à jour: exemple de code.

@Test
public void myTest() {
  when(service.foo(any(), new ARequest(1, "A"))).thenReturn(new AResponse(1, "passed"));
  when(service.foo(any(), new ARequest(2, "2A"))).thenReturn(new AResponse(2, "passed"));
  when(service.foo(any(), new BRequest(1, "B"))).thenReturn(new BResponse(112, "passed"));

  c.execute();
}

public class ClassUnderTest {
  Service service = new Service();
  public void execute() {
    AResponse ar = (AResponse) service.foo("A1", new ARequest(1, "A"));
    AResponse ar2 = (AResponse) service.foo("A2", new ARequest(2, "2A"));
    BResponse br = (BResponse) service.foo("B1", new BRequest(1, "B"));
  }
}

public class Service {
  public Object foo(String firstArgument, Object obj) {
    return null; //return something
  }
}
15
Zeeshan Bilal

Une solution pourrait consister à éviter d’être trop restrictif dans vos arguments afin de fournir tous les résultats attendus avec un seul appel thenReturn.

Par exemple, disons que je veux me moquer de cette méthode:

public String foo(String firstArgument, Object obj) {
    return "Something";
}

Vous pouvez ensuite vous en moquer en fournissant autant de résultats que vous le souhaitez, comme ci-dessous:

// Mock the call of foo of any String to provide 3 results
when(mock.foo(anyString(), anyObject())).thenReturn("val1", "val2", "val3");

Les appels à foo avec tous les paramètres fourniront respectivement "val1", "val2", puis tous les appels suivants fourniront "val3".


Si vous vous souciez des valeurs passées mais que vous ne voulez pas dépendre de la séquence des appels, vous pouvez utiliser thenAnswer pour fournir une réponse correspondant au deuxième argument, comme vous le faites actuellement, mais avec 3 thenReturn différents.

when(mock.foo(anyString(), anyObject())).thenAnswer(
    invocation -> {
        Object argument = invocation.getArguments()[1];
        if (argument.equals(new ARequest(1, "A"))) {
            return new AResponse(1, "passed");
        } else if (argument.equals(new ARequest(2, "2A"))) {
            return new AResponse(2, "passed");
        } else if (argument.equals(new BRequest(1, "B"))) {
            return new BResponse(112, "passed");
        }
        throw new InvalidUseOfMatchersException(
            String.format("Argument %s does not match", argument)
        );
    }
);
22
Nicolas Filotto

La méthode appropriée consiste à faire correspondre les arguments à l'aide de eq(), mais si vous ne le souhaitez pas, vous pouvez simplement enregistrer plusieurs valeurs de retour.

when(someService.doSomething(any(SomeParam.class))).thenReturn(
  firstReturnValue, secondReturnValue, thirdReturnValue
);

Désormais, le premier appel renverra firstValue, le deuxième secondValue et tous les suivants thirdValue.

3
Sean Patrick Floyd

Je pense: la méthode "recommandée" serait celle qui fonctionne pour vous; et cela vient avec le moins d'efforts de codage.

Vous devez obligatoirement fournir CEUX qui sont nécessaires pour que votre test fasse ce qu’il doit faire. Il n'y a pas de chemin aux alentours.

Si vous vous souciez vraiment des arguments utilisés, vous devez les spécifier en conséquence. Si vous vous en fiche utilisez any()

0
Tom Bulgur