Wie verwende ich ArgumentCaptor zum Stubben?

161

In Mockito- Dokumentation und Javadocs heißt es

Es wird empfohlen, ArgumentCaptor zur Überprüfung, jedoch nicht zum Stubbing zu verwenden.

Ich verstehe jedoch nicht, wie ArgumentCaptor zum Stubben verwendet werden kann. Kann jemand die obige Aussage erklären und zeigen, wie ArgumentCaptor zum Stubben verwendet werden kann, oder einen Link bereitstellen, der zeigt, wie dies getan werden kann?

Kann nicht sagen
quelle
1
Super kurze und nette Erklärung hier: dzone.com/articles/…
Benj

Antworten:

271

Angenommen, die folgende Testmethode:

public boolean doSomething(SomeClass arg);

In der Mockito-Dokumentation heißt es, dass Sie Captor nicht folgendermaßen verwenden sollten:

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

Weil Sie Matcher nur während des Stubbens verwenden können:

when(someObject.doSomething(eq(expected))).thenReturn(true);

Die Überprüfung ist jedoch eine andere Geschichte. Wenn Ihr Test sicherstellen muss, dass diese Methode mit einem bestimmten Argument aufgerufen wurde, verwenden Sie ArgumentCaptorund dies ist der Fall, für den sie entwickelt wurde:

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));
Rorick
quelle
Danke für die Antwort. Ich habe eine Frage. Im dritten Codeblock wissen wir, dass true nur zurückgegeben wird, wenn erwartet an doSomething übergeben wird. Aber wann wird true im zweiten Codeblock zurückgegeben? Oder gibt someObject in diesem Fall immer true für someMethod zurück?
Kann nicht sagen,
Hm, ich glaube du hast gemeint "Aber wann wird true im dritten Codeblock zurückgegeben?". Im dritten Codeblock kümmern wir uns einfach nicht um den Rückgabewert und lassen ihn als Standardwert sein. Für Boolesche ist es falsenicht true.
Rorick
Nein, ich habe alle grauen Hintergrundblöcke als Codeblöcke gezählt. Einschließlich des ersten Liners. Ich bezog mich auf die Zeile when (someObject.doSomething (argumentCaptor.capture ())). ThenReturn (true);
Kann nicht sagen,
Oh, tut mir leid. Ja, in diesem Fall wird true immer zurückgegeben.
Rorick
3
Ich bin mir nicht sicher, ob der Grund, "nicht mit Stubbing zu verwenden", ein einfacher Grund ist. Matcher geben uns nicht das tatsächlich erwartete Argument (nur den Typ) und führen dazu, dass Tests trotz Argumenten, die möglicherweise falsch sind, in Ordnung sind.
dtc
0

Die Linie

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

würde das gleiche tun wie

when(someObject.doSomething(Matchers.any())).thenReturn(true);

Die Verwendung von argumentCaptor.capture () beim Stubbing hat also keinen Mehrwert. Die Verwendung von Matchers.any () zeigt besser, was wirklich passiert, und ist daher besser lesbar. Mit argumentCaptor.capture () können Sie nicht lesen, welche Argumente wirklich übereinstimmen. Und anstatt any () zu verwenden, können Sie spezifischere Matcher verwenden, wenn Sie mehr Informationen haben (Klasse des erwarteten Arguments), um Ihren Test zu verbessern.

Und noch ein Problem: Wenn Sie beim Stubben argumentCaptor.capture () verwenden, wird unklar, wie viele Werte nach der Überprüfung voraussichtlich erfasst werden. Wir möchten einen Wert während der Überprüfung erfassen, nicht während des Stubbens, da zu diesem Zeitpunkt noch kein Wert erfasst werden muss. Was erfassen die Argumenterfassungsmethoden während des Stubbens? oder erfasst es nichts? Ich habe keine Antwort auf diese Frage. Ich betrachte es als undefiniertes Verhalten und möchte kein undefiniertes Verhalten verwenden.

Stefan Mondelaers
quelle
0

Wenn Sie bei der Suche auf diese Frage gestoßen sind, möchten Sie wahrscheinlich Folgendes:

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

Warum? Denn wie ich schätzen Sie die Zeit und werden sie nicht .equalsnur für das einzelne Testszenario implementieren .

Und 99% der Tests fallen auseinander, wenn von Mock null zurückgegeben wird, und in einem vernünftigen Design würden Sie die Rückgabe nullum jeden Preis vermeiden , verwenden Optionaloder nach Kotlin umziehen. Dies bedeutet, dass verifydies nicht so oft verwendet werden muss und ArgumentCaptors einfach zu mühsam zum Schreiben sind.

Aubergine
quelle