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 MockingProgressclasse 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 mockmetodo della Mockitoclasse, questo è essenzialmente ciò che accade:
Mockito.mockdelega a org.mockito.internal.MockitoCore.mock, passando le impostazioni fittizie predefinite come parametro.
MockitoCore.mockdelegati a org.mockito.internal.util.MockUtil.createMock
- La
MockUtilclasse utilizza la ClassPathLoaderclasse per ottenere un'istanza MockMakerda utilizzare per creare il mock. Per impostazione predefinita, viene utilizzata la classe CgLibMockMaker .
CgLibMockMakerutilizza una classe presa in prestito da JMock, ClassImposterizerche gestisce la creazione del mock. I pezzi chiave della "magia mockito" utilizzati sono MethodInterceptorusati per creare il mock: il mockito MethodInterceptorFiltere 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 MockHandleristanze, che alla fine delegano a MockHandlerImpl#handle. Durante MockHandlerImpl#handle, il gestore fittizio crea un'istanza di OngoingStubbingImple la passa MockingProgressall'istanza condivisa .
Quando il whenmetodo 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 MockingProgresscui è stata method()scritta l'invocazione derisa e la restituisce. Quindi il thenReturnmetodo viene quindi chiamato OngoingStubbingsull'istanza.