La réponse courte est que dans votre exemple, le résultat d' mock.method()
va être d'un type approprié valeur vide; mockito utilise indirection via l'utilisation de proxy, la méthode d'interception, et une instance partagée de l' MockingProgress
de la classe afin de déterminer si une invocation d'une méthode sur un objet fantaisie pour cogner ou de relecture d'un écrasé le comportement plutôt que sur la transmission de l'information au sujet de buter par la valeur de retour d'une moqué de méthode.
Une mini-analyse dans un couple de minutes à regarder la mockito code est comme suit. Remarque, c'est un très approximative de la description il y a beaucoup de détails dans le jeu ici. Je vous suggère de consulter la source sur github vous-même.
Tout d'abord, lorsque vous vous moquez d'une classe à l'aide de l' mock
méthode de Mockito
classe, c'est essentiellement ce qui se passe:
-
Mockito.mock
délégués org.mockito.internal.MockitoCore
.fantaisie, en passant par défaut se moquer de paramètres en tant que paramètre.
-
MockitoCore.mock
délégués org.mockito.internal.util.MockUtil
.createMock
- L'
MockUtil
classe utilise l' ClassPathLoader
classe pour obtenir une instance de l' MockMaker
à utiliser pour créer la maquette. Par défaut, le CgLibMockMaker classe est utilisée.
-
CgLibMockMaker
utilise une classe emprunté JMock, ClassImposterizer
qui traite de la création de la maquette. Les éléments clés de la "mockito magique" utilisés sont l' MethodInterceptor
utilisé pour créer la maquette: le mockito MethodInterceptorFilter
, et une chaîne de MockHandler les instances, y compris une instance de MockHandlerImpl. La méthode de l'intercepteur passe invocations à MockHandlerImpl exemple, qui met en œuvre la logique d'entreprise qui doivent être appliquées lorsqu'une méthode est appelée sur une maquette (c'est à dire, cherchant à voir si une réponse est enregistrée déjà, afin de déterminer si l'invocation représente un nouveau tampon, etc. L'état par défaut, c'est que si un talon n'est pas déjà inscrits pour la méthode invoquée, un type approprié vide , la valeur renvoyée.
Maintenant, regardons le code dans votre exemple:
when(mock.method()).thenReturn(someValue)
Voici l'ordre que ce code s'exécute dans:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
La clé pour comprendre ce qui se passe, c'est ce qui se passe lorsque la méthode de la maquette est invoquée: la méthode de l'intercepteur est passé de l'information sur l'invocation de la méthode, et les délégués à la chaîne d' MockHandler
des cas, ce qui a finalement délégué MockHandlerImpl#handle
. Au cours MockHandlerImpl#handle
, les modèles de gestionnaire d'crée une instance de OngoingStubbingImpl
et passe à l'partagé MockingProgress
de l'instance.
Lorsque l' when
méthode est appelée après l'invocation de l' method()
, il délègue à d' MockitoCore.when
, qui appelle l' stub()
méthode de la même classe. Cette méthode présente les cours buter par le partage de l' MockingProgress
de l'instance qui le raillaient method()
invocation a écrit dans, et le renvoie. Ensuite, thenReturn
méthode est appelée sur l' OngoingStubbing
de l'instance.