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 MockingProgressclasse 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 mockmétodo da Mockitoclasse, é essencialmente o que acontece:
Mockito.mockdelegados para org.mockito.internal.MockitoCore.mock, passando as configurações de simulação padrão como um parâmetro.
MockitoCore.mockdelegados para org.mockito.internal.util.MockUtil.createMock
- A
MockUtilclasse usa a ClassPathLoaderclasse para obter uma instância de MockMakerpara usar para criar a simulação. Por padrão, a classe CgLibMockMaker é usada.
CgLibMockMakerusa uma classe emprestada do JMock, ClassImposterizerque lida com a criação do mock. As peças-chave da 'magia mockito' usadas são as MethodInterceptorusadas para criar o mockito: o mockito MethodInterceptorFiltere 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 MockHandlerinstâncias, que eventualmente delega para MockHandlerImpl#handle. Durante MockHandlerImpl#handle, o manipulador de simulação cria uma instância de OngoingStubbingImple a passa para a MockingProgressinstância compartilhada .
Quando o whenmé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 MockingProgressinstância compartilhada em que a method()invocação simulada escreveu e o retorna. Então, o thenReturnmétodo é então chamado na OngoingStubbinginstância.