Die kurze Antwort lautet, dass in Ihrem Beispiel das Ergebnis von mock.method()ein typgerechter leerer Wert ist. mockito verwendet die Indirektion über Proxy, Abfangen von Methoden und eine gemeinsam genutzte Instanz der MockingProgressKlasse, um zu bestimmen, ob ein Aufruf einer Methode auf einem Mock zum Stubben oder Wiedergeben eines vorhandenen Stubbed-Verhaltens dient, anstatt Informationen über das Stubbing über den Rückgabewert von zu übergeben eine verspottete Methode.
Eine Mini-Analyse in wenigen Minuten mit Blick auf den Mockito-Code lautet wie folgt. Beachten Sie, dass dies eine sehr grobe Beschreibung ist - hier sind viele Details im Spiel. Ich schlage vor, dass Sie die Quelle auf Github selbst überprüfen .
Wenn Sie eine Klasse mit der mockMethode der MockitoKlasse verspotten , geschieht im Wesentlichen Folgendes:
Mockito.mockdelegiert an org.mockito.internal.MockitoCore.mock und übergibt die Standard-Mock-Einstellungen als Parameter.
MockitoCore.mockdelegiert an org.mockito.internal.util.MockUtil.createMock
- Die
MockUtilKlasse verwendet die ClassPathLoaderKlasse, um eine Instanz MockMakerzum Erstellen des Mocks abzurufen. Standardmäßig wird die CgLibMockMaker- Klasse verwendet.
CgLibMockMakerverwendet eine von JMock entliehene Klasse, ClassImposterizerdie das Erstellen des Mocks übernimmt. Die Schlüsselelemente der verwendeten 'Mockito-Magie' sind die MethodInterceptorzum Erstellen des Mocks verwendeten: der Mockito MethodInterceptorFilterund eine Kette von MockHandler-Instanzen, einschließlich einer Instanz von MockHandlerImpl . Der Methoden-Interceptor übergibt Aufrufe an die MockHandlerImpl-Instanz, die die Geschäftslogik implementiert, die angewendet werden soll, wenn eine Methode für einen Mock aufgerufen wird (dh sucht, ob bereits eine Antwort aufgezeichnet wurde, und ermittelt, ob der Aufruf einen neuen Stub darstellt usw.). Der Standardstatus ist, dass ein typgerechter leerer Wert zurückgegeben wird, wenn für die aufgerufene Methode noch kein Stub registriert ist.
Schauen wir uns nun den Code in Ihrem Beispiel an:
when(mock.method()).thenReturn(someValue)
Hier ist die Reihenfolge, in der dieser Code ausgeführt wird:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
Der Schlüssel zum Verständnis der Vorgänge liegt darin, was passiert, wenn die Methode auf dem Mock aufgerufen wird: Dem Methodenabfangjäger werden Informationen über den Methodenaufruf übergeben und an seine MockHandlerInstanzkette delegiert, an die schließlich delegiert wird MockHandlerImpl#handle. Währenddessen erstellt MockHandlerImpl#handleder Mock-Handler eine Instanz von OngoingStubbingImplund übergibt sie an die gemeinsam genutzte MockingProgressInstanz.
Wenn die whenMethode nach dem Aufruf von aufgerufen wird method(), delegiert sie an MockitoCore.when, wodurch die stub()Methode derselben Klasse aufgerufen wird . Diese Methode entpackt das laufende Stubbing aus der gemeinsam genutzten MockingProgressInstanz, in die der verspottete method()Aufruf geschrieben hat, und gibt es zurück. Dann wird die thenReturnMethode für die OngoingStubbingInstanz aufgerufen .