La respuesta corta es que en su ejemplo, el resultado de mock.method()
será un valor vacío apropiado para el tipo; mockito usa indirección a través de proxy, interceptación de métodos y una instancia compartida de la MockingProgress
clase para determinar si una invocación de un método en un simulacro es para apuntar o reproducir un comportamiento stubbed existente en lugar de pasar información sobre stubbing a través del valor de retorno de un método burlado.
Un mini-análisis en un par de minutos mirando el código mockito es el siguiente. Tenga en cuenta que esta es una descripción muy aproximada: hay muchos detalles en juego aquí. Le sugiero que consulte la fuente en github usted mismo.
Primero, cuando te burlas de una clase usando el mock
método de la Mockito
clase, esto es esencialmente lo que sucede:
Mockito.mock
delegados a org.mockito.internal.MockitoCore
.mock, pasando la configuración de simulación predeterminada como parámetro.
MockitoCore.mock
delegados a org.mockito.internal.util.MockUtil
.createMock
- La
MockUtil
clase usa la ClassPathLoader
clase para obtener una instancia de MockMaker
usar para crear el simulacro. De forma predeterminada, se utiliza la clase CgLibMockMaker .
CgLibMockMaker
usa una clase prestada de JMock, ClassImposterizer
que se encarga de crear el simulacro. Las piezas clave de la 'magia mockito' utilizadas son las MethodInterceptor
utilizadas para crear el mock: el mockito MethodInterceptorFilter
y una cadena de instancias de MockHandler, incluida una instancia de MockHandlerImpl . El interceptor de métodos pasa las invocaciones a la instancia de MockHandlerImpl, que implementa la lógica de negocios que se debe aplicar cuando se invoca un método en un simulacro (es decir, buscar para ver si una respuesta ya está registrada, determinar si la invocación representa un nuevo stub, etc. El estado predeterminado es que si un código auxiliar aún no está registrado para el método que se invoca, se devuelve un valor vacío apropiado para el tipo .
Ahora, veamos el código en su ejemplo:
when(mock.method()).thenReturn(someValue)
Este es el orden en el que se ejecutará este código:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
La clave para comprender lo que está sucediendo es lo que sucede cuando se invoca el método en el simulacro: al interceptor del método se le pasa información sobre la invocación del método, y delega en su cadena de MockHandler
instancias, que eventualmente delega en MockHandlerImpl#handle
. Durante MockHandlerImpl#handle
, el controlador simulado crea una instancia de OngoingStubbingImpl
y la pasa a la MockingProgress
instancia compartida .
Cuando el when
método se invoca después de la invocación de method()
, delega en MockitoCore.when
, que llama al stub()
método de la misma clase. Este método descomprime el stubbing en curso de la MockingProgress
instancia compartida en la que method()
escribió la invocación simulada y lo devuelve. Luego thenReturn
, se llama al método en la OngoingStubbing
instancia.