it-swarm.com.de

Mock gleiche Methode mit verschiedenen Parametern

Ich benutze mockito, um meinen Geschäftsservice zu testen, und es verwendet ein Dienstprogramm, das ich verspotten möchte. Es gibt mindestens 2-3 Aufrufe in jeder Servicemethode für das Dienstprogramm mit unterschiedlichen Argumenten. 

Gibt es eine empfohlene Möglichkeit, mehrere when(...).thenReturn(...) für dieselbe Methode, aber unterschiedliche Argumente zu verwenden?

Ich möchte auch any() marcher im Inneren verwenden. Ist es möglich?

Update: Beispielcode.

@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

Eine Möglichkeit wäre, zu vermeiden, dass Ihre Argumente zu restriktiv sind, um alle erwarteten Ergebnisse mit nur einem Aufruf von thenReturn bereitzustellen.

Nehmen wir zum Beispiel an, ich möchte diese Methode verspotten:

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

Sie könnten es dann verspotten, indem Sie unten so viele Ergebnisse wie gewünscht liefern:

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

Aufrufe an foo mit beliebigen Parametern liefern jeweils "val1", "val2". Bei nachfolgenden Aufrufen wird "val3" angegeben.


Wenn Sie sich für übergebene Werte interessieren, aber nicht auf die Anrufsequenz angewiesen sein möchten, können Sie mit thenAnswer eine Antwort angeben, die mit dem zweiten Argument übereinstimmt, wie Sie es derzeit tun, aber mit 3 verschiedenen thenReturn.

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

Die richtige Methode wäre, die Argumente mit eq() abzugleichen. Wenn Sie dies nicht möchten, können Sie einfach mehrere Rückgabewerte aufzeichnen.

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

Beim ersten Aufruf werden jetzt firstValue, die zweite secondValue und alle folgenden thirdValue zurückgegeben.

3

Ich denke: Der "empfohlene" Weg wäre der, der für Sie FUNKTIONIERT. und das kommt mit dem geringsten Aufwand an Kodierung.

Sie müssen DIESE Spezifikationen bereitstellen, die erforderlich sind, damit Ihr Test das macht, was er tun muss. Daran führt kein Weg vorbei.

Wenn Ihnen die verwendeten Argumente wirklich wichtig sind, müssen Sie sie entsprechend angeben. Wenn es dir egal ist; benutze any()

0
Tom Bulgur