La réponse courte est que dans votre exemple, le résultat de mock.method()
sera une valeur vide appropriée au type; mockito utilise l'indirection via le proxy, l'interception de méthode et une instance partagée de la MockingProgress
classe afin de déterminer si une invocation d'une méthode sur une maquette est pour le stubbing ou la relecture d'un comportement stubbed existant plutôt que de transmettre des informations sur le stubbing via la valeur de retour de une méthode moquée.
Une mini-analyse en quelques minutes en regardant le code mockito est la suivante. Notez qu'il s'agit d'une description très approximative - il y a beaucoup de détails en jeu ici. Je vous suggère de vérifier vous-même la source sur github .
Tout d'abord, lorsque vous vous moquez d'une classe en utilisant la mock
méthode de la Mockito
classe, c'est essentiellement ce qui se passe:
Mockito.mock
délègue à org.mockito.internal.MockitoCore
.mock, en passant les paramètres de simulation par défaut en tant que paramètre.
MockitoCore.mock
délègue à org.mockito.internal.util.MockUtil
.createMock
- La
MockUtil
classe utilise la ClassPathLoader
classe pour obtenir une instance de MockMaker
à utiliser pour créer la maquette. Par défaut, la classe CgLibMockMaker est utilisée.
CgLibMockMaker
utilise une classe empruntée à JMock, ClassImposterizer
qui gère la création de la maquette. Les éléments clés de la «magie mockito» utilisés sont ceux MethodInterceptor
utilisés pour créer le simulacre: le mockito MethodInterceptorFilter
, et une chaîne d'instances MockHandler, y compris une instance de MockHandlerImpl . L'intercepteur de méthode passe les appels à l'instance MockHandlerImpl, qui implémente la logique métier à appliquer lorsqu'une méthode est invoquée sur un simulacre (c'est-à-dire, en cherchant à voir si une réponse est déjà enregistrée, en déterminant si l'appel représente un nouveau stub, etc. L'état par défaut est que si un stub n'est pas déjà inscrit pour la méthode appelée, une valeur vide appropriée au type est renvoyée.
Maintenant, regardons le code dans votre exemple:
when(mock.method()).thenReturn(someValue)
Voici l'ordre dans lequel ce code s'exécutera:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
La clé pour comprendre ce qui se passe est ce qui se passe lorsque la méthode sur la maquette est appelée: l'intercepteur de méthode reçoit des informations sur l'appel de méthode et les délègue à sa chaîne d' MockHandler
instances, qui finit par déléguer à MockHandlerImpl#handle
. Pendant MockHandlerImpl#handle
, le gestionnaire de simulation crée une instance de OngoingStubbingImpl
et la transmet à l' MockingProgress
instance partagée .
Lorsque la when
méthode est appelée après l'appel de method()
, elle délègue à MockitoCore.when
, qui appelle la stub()
méthode de la même classe. Cette méthode décompresse le stubbing en cours de l' MockingProgress
instance partagée dans laquelle l' method()
appel simulé a écrit et la renvoie. Ensuite, la thenReturn
méthode est appelée sur l' OngoingStubbing
instance.