A resposta curta é que em seu exemplo, o resultado de mock.method()
será um valor vazio apropriado ao tipo; mockito usa indireção via proxy, interceptação de método e uma instância compartilhada da MockingProgress
classe a fim de determinar se uma invocação de um método em um mock é para stubbing ou repetição de um comportamento de stub existente em vez de passar informações sobre stub por meio do valor de retorno de um método simulado.
Uma mini-análise em alguns minutos examinando o código do mockito é a seguinte. Observe, esta é uma descrição muito aproximada - há muitos detalhes em jogo aqui. Eu sugiro que você verifique a fonte no github .
Primeiro, quando você simula uma classe usando o mock
método da Mockito
classe, é essencialmente o que acontece:
Mockito.mock
delegados para org.mockito.internal.MockitoCore
.mock, passando as configurações de simulação padrão como um parâmetro.
MockitoCore.mock
delegados para org.mockito.internal.util.MockUtil
.createMock
- A
MockUtil
classe usa a ClassPathLoader
classe para obter uma instância de MockMaker
para usar para criar a simulação. Por padrão, a classe CgLibMockMaker é usada.
CgLibMockMaker
usa uma classe emprestada do JMock, ClassImposterizer
que lida com a criação do mock. As peças-chave da 'magia mockito' usadas são as MethodInterceptor
usadas para criar o mockito: o mockito MethodInterceptorFilter
e uma cadeia de instâncias de MockHandler, incluindo uma instância de MockHandlerImpl . O interceptor de método passa invocações para a instância MockHandlerImpl, que implementa a lógica de negócios que deve ser aplicada quando um método é invocado em uma simulação (ou seja, procurando ver se uma resposta já foi gravada, determinando se a invocação representa um novo stub, etc. O estado padrão é que se um stub ainda não estiver registrado para o método que está sendo chamado, um valor vazio apropriado ao tipo é retornado.
Agora, vamos examinar o código em seu exemplo:
when(mock.method()).thenReturn(someValue)
Esta é a ordem em que este código será executado:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
A chave para entender o que está acontecendo é o que acontece quando o método no mock é invocado: o interceptor do método recebe informações sobre a invocação do método e delega para sua cadeia de MockHandler
instâncias, que eventualmente delega para MockHandlerImpl#handle
. Durante MockHandlerImpl#handle
, o manipulador de simulação cria uma instância de OngoingStubbingImpl
e a passa para a MockingProgress
instância compartilhada .
Quando o when
método é invocado após a invocação de method()
, ele delega para MockitoCore.when
, que chama o stub()
método da mesma classe. Este método descompacta o stub em andamento da MockingProgress
instância compartilhada em que a method()
invocação simulada escreveu e o retorna. Então, o thenReturn
método é então chamado na OngoingStubbing
instância.