La risposta breve è che nel tuo esempio, il risultato di mock.method()
sarà un valore vuoto appropriato per il tipo; mockito utilizza l'indirizzamento tramite proxy, intercettazione del metodo e un'istanza condivisa della MockingProgress
classe per determinare se un'invocazione di un metodo su un mock è per lo stubbing o la riproduzione di un comportamento stubbed esistente piuttosto che passare informazioni sullo stubbing tramite il valore di ritorno di un metodo deriso.
Una mini-analisi in un paio di minuti guardando il codice mockito è la seguente. Nota, questa è una descrizione molto approssimativa: ci sono molti dettagli in gioco qui. Ti suggerisco di controllare tu stesso la fonte su GitHub .
Innanzitutto, quando deridi una classe usando il mock
metodo della Mockito
classe, questo è essenzialmente ciò che accade:
Mockito.mock
delega a org.mockito.internal.MockitoCore
.mock, passando le impostazioni fittizie predefinite come parametro.
MockitoCore.mock
delegati a org.mockito.internal.util.MockUtil
.createMock
- La
MockUtil
classe utilizza la ClassPathLoader
classe per ottenere un'istanza MockMaker
da utilizzare per creare il mock. Per impostazione predefinita, viene utilizzata la classe CgLibMockMaker .
CgLibMockMaker
utilizza una classe presa in prestito da JMock, ClassImposterizer
che gestisce la creazione del mock. I pezzi chiave della "magia mockito" utilizzati sono MethodInterceptor
usati per creare il mock: il mockito MethodInterceptorFilter
e una catena di istanze MockHandler, inclusa un'istanza di MockHandlerImpl . L'intercettore del metodo passa le invocazioni all'istanza MockHandlerImpl, che implementa la logica di business che dovrebbe essere applicata quando un metodo viene invocato su un mock (cioè, cercando per vedere se una risposta è già registrata, determinando se l'invocazione rappresenta un nuovo stub, ecc. Lo stato predefinito è che se uno stub non è già registrato per il metodo richiamato, viene restituito un valore vuoto appropriato per il tipo .
Ora, diamo un'occhiata al codice nel tuo esempio:
when(mock.method()).thenReturn(someValue)
Ecco l'ordine in cui verrà eseguito questo codice:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
La chiave per capire cosa sta succedendo è cosa succede quando viene richiamato il metodo sul mock: all'intercettore del metodo vengono passate le informazioni sulla chiamata del metodo e le delega alla sua catena di MockHandler
istanze, che alla fine delegano a MockHandlerImpl#handle
. Durante MockHandlerImpl#handle
, il gestore fittizio crea un'istanza di OngoingStubbingImpl
e la passa MockingProgress
all'istanza condivisa .
Quando il when
metodo viene invocato dopo l'invocazione di method()
, delega a MockitoCore.when
, che chiama il stub()
metodo della stessa classe. Questo metodo decomprime lo stubbing in corso dall'istanza condivisa in MockingProgress
cui è stata method()
scritta l'invocazione derisa e la restituisce. Quindi il thenReturn
metodo viene quindi chiamato OngoingStubbing
sull'istanza.