Mockito - Unterschied zwischen doReturn () und when ()


196

Ich bin derzeit dabei, Mockito zum Verspotten meiner Service-Layer-Objekte in einer Spring MVC-Anwendung zu verwenden, in der ich meine Controller-Methoden testen möchte. Als ich jedoch über die Besonderheiten von Mockito gelesen habe, habe ich festgestellt, dass die Methoden doReturn(...).when(...)äquivalent zu sind when(...).thenReturn(...). Meine Frage ist also, was bringt es, zwei Methoden zu haben, die dasselbe tun, oder was ist der subtile Unterschied zwischen doReturn(...).when(...)und when(...).thenReturn(...)?

Jede Hilfe wäre dankbar.


1
Der Javadoc hat einige Fälle, in denen dies doReturn()nützlich ist.
Sotirios Delimanolis

5
Ich denke, einer der Hauptunterschiede ist, dass doReturn (...). When (..) älter ist und nicht so sicher ist. Daher können wir es manchmal verwenden, wenn sich der Compiler immer wieder über das Casting beschwert. Das when (..). ThenReturn (..) ist in Bezug auf die
Typensicherheit

Antworten:


227

Die beiden Syntaxen für das Stubbing sind ungefähr gleichwertig. Sie können jedoch immer verwenden doReturn/whenfür Anstoßen; Es gibt jedoch Fälle, in denen Sie nicht verwenden können when/thenReturn. Das Stubben von Hohlraummethoden ist eine solche. Andere beinhalten die Verwendung mit Mockito-Spionen und das mehrmalige Stubben derselben Methode.

Eine Sache, when/thenReturndie Ihnen das doReturn/whengibt, ist die Typprüfung des Wertes, den Sie zur Kompilierungszeit zurückgeben. Ich glaube jedoch, dass dies fast keinen Wert hat - wenn Sie den Typ falsch angegeben haben, werden Sie es herausfinden, sobald Sie Ihren Test ausführen.

Ich empfehle dringend nur zu verwenden doReturn/when. Es macht keinen Sinn, zwei Syntaxen zu lernen, wenn eine ausreicht.

Vielleicht möchten Sie sich auf meine Antwort unter Forming Mockito "Grammatiken" beziehen - eine detailliertere Antwort auf eine sehr eng verwandte Frage.


16
Ich bin nicht einverstanden mit David. Ich stoße oft auf Situationen, in denen ich bei der Verwendung den falschen Typ zurückgebe doReturn/whenund die nächsten Minuten damit verbringe, herauszufinden, was schief gelaufen ist. Die Überprüfung des Kompiliertyps wird mit äußerst nützlich when/thenReturn.
Saket

11
Denken Sie daran, dass Mockito die Verwendung when/thenReturnanstelle von empfiehlt doReturn/when.
CodyEngel

2
@CodyEngel und es gibt keinen Grund für eine solche Empfehlung, außer dem, was ich in meinen Antworten hier und unter stackoverflow.com/q/11462697 dargelegt habe . Vor einigen Jahren habe ich dies mit Brice Dutheil besprochen, der derzeit als Hauptentwickler von Mockito fungiert, und nach bestem Wissen stimmt er zu. Ich werde ihn bitten, hier einen Kommentar zu schreiben (keine Garantie, dass er dies tut).
Dawood ibn Kareem

18
Der Javadoc gibt an, dass dies doReturn/whenein Kompromiss ist. Das Team empfiehlt nicht auf die eine oder andere Weise, stellt jedoch fest, dass der when/thenAnsatz intuitiver und lesbarer ist und eine Überprüfung der Kompilierungszeit bietet. Dieser Ansatz hat Mockito populär und benutzerfreundlich gemacht. Vergessen Sie dies nicht, wenn die Codebasis von gemeinsam genutzt wird verschiedene Fähigkeiten in Ihrem Team; Dennoch hat es Nachteile in Bezug auf Spione und Leermethoden.
Brice

5
Nur zur Veranschaulichung : Hat doReturn()den großen Nachteil, dass Methodenaufrufe im YODA-Stil codiert werden. Die Sache wird später als erstes aufgeschrieben. Die meisten Leute lesen von links nach rechts; Sie müssen jetzt ständig daran denken, die Return-When-Logik in Ihrem Kopf umzukehren.
GhostCat

199

Beide Ansätze verhalten sich unterschiedlich, wenn Sie ein Spionageobjekt (mit Anmerkungen versehen @Spy) anstelle eines Scheinobjekts (mit Anmerkungen versehen @Mock) verwenden:

  • when(...) thenReturn(...) führt einen echten Methodenaufruf durch, kurz bevor der angegebene Wert zurückgegeben wird. Wenn die aufgerufene Methode eine Ausnahme auslöst, müssen Sie sich damit befassen / sie verspotten usw. Natürlich erhalten Sie immer noch Ihr Ergebnis (was Sie in definieren thenReturn(...)).

  • doReturn(...) when(...) ruft die Methode überhaupt nicht auf .

Beispiel:

public class MyClass {
     protected String methodToBeTested() {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Prüfung:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

37
Dieses Verhalten funktioniert nur für ausspionierte Objekte, da es sich um "Wrapper" realer Objekte handelt. Bei verspotteten Objekten spielt es keine Rolle, ob es wann / thenReturn oder doReturn / wann ist. Verspottete Objekte rufen niemals echte Methoden auf.
Rafael Orágio

Könnten Sie bitte weitere Informationen geben, warum wir diese Funktionalität verwenden müssen? Ich sehe keinen praktischen Anwendungsfall. Die Absicht des Tests ist es, die Richtigkeit des Codes unter verschiedenen Anwendungsfällen zu bestätigen. Wenn der Aufruf der Methode einen Ausnahmetest auslöst, sollte er eine Ausnahme
auslösen

@Gleichmut Dies war ein hypothetisches Szenario, in dem ich die Verwendung / den Vorteil von doReturn zeige. In einer realen Anwendung macht eine Methode, die nur eine Ausnahme zurückgibt, natürlich keinen Sinn. Aber Sie haben Methoden (wahrscheinlich nicht so dünn wie diese), die unter bestimmten Bedingungen Ausnahmen
auslösen

1
Nur zur Verdeutlichung: Die Methode when (). ThenReturn () - ruft die eigentliche Methode (eines Spions - spielt für Mocks keine Rolle) nur einmal auf. Dies geschieht in der Zeile, in der Sie das Scheinverhalten angeben (when ( myClass.anotherMethodInClass () .thenRet ...). Danach wird die eigentliche Methode nie wieder aufgerufen. Vielleicht gut zu wissen, ob Sie beim Lesen der Erklärung eine Dekorationslogik erwartet haben oben.
Jonas

Dies scheint kein Vorteil zu sein doReturn(), es sieht aus wie ein Missbrauch der Bibliothek. Der Sinn des Spionierens statt des reinen Verspottens besteht darin, echte Anrufe zu nutzen. Sie warnen auch davor, Spies wie diesen zu verwenden: github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes) (und empfehlen, die Klasse zu erweitern und stattdessen die Methode zu überschreiben)
Matthew Read

13

Das Mockito-Javadoc scheint zu erklären , warum in den seltenen Fällen, in denen Sie Mockito.when (Object) nicht verwenden können, doReturn () doReturn()anstelle von when()Use doReturn () verwendet wird.

Beachten Sie, dass Mockito.when (Object) immer zum Stubben empfohlen wird, da es argumenttypsicher und lesbarer ist (insbesondere beim Stubben aufeinanderfolgender Aufrufe).

Hier sind die seltenen Fälle, in denen doReturn () nützlich ist:

1. Wenn Sie echte Objekte ausspionieren und echte Methoden für einen Spion aufrufen, treten Nebenwirkungen auf

List list = new LinkedList(); List spy = spy(list);

// Unmöglich: Die echte Methode wird aufgerufen, daher löst spy.get (0) die IndexOutOfBoundsException aus (die Liste ist noch leer).

when(spy.get(0)).thenReturn("foo");

// Sie müssen doReturn () zum Stubben verwenden: doReturn("foo").when(spy).get(0);

2. Überschreiben einer vorherigen Ausnahme-Stubbing:

when(mock.foo()).thenThrow(new RuntimeException());

// Unmöglich: Die ausnahme-stubbed foo () -Methode wird aufgerufen, sodass RuntimeException ausgelöst wird. when(mock.foo()).thenReturn("bar");

// Sie müssen doReturn () zum Stubben verwenden:

doReturn("bar").when(mock).foo(); Die obigen Szenarien zeigen einen Kompromiss zwischen Mockitos eleganter Syntax. Beachten Sie jedoch, dass die Szenarien sehr selten sind. Spionage sollte sporadisch sein und übergeordnetes Ausnehmen von Ausnahmen ist sehr selten. Ganz zu schweigen davon, dass das Überschreiben von Stubbing im Allgemeinen ein potenzieller Codegeruch ist, der auf zu viel Stubbing hinweist.


6

Wenn Sie diese Antwort fortsetzen , gibt es einen weiteren Unterschied: Wenn Sie möchten, dass Ihre Methode unterschiedliche Werte zurückgibt, z. B. beim ersten Aufruf, beim zweiten Aufruf usw., können Sie beispielsweise Werte übergeben ...

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

Es wird also false zurückgegeben, wenn die Methode im selben Testfall aufgerufen wird, und dann wird false erneut und zuletzt true zurückgegeben.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.