Mockito when() methodIt enables stubbing methods. It should be used when we want to mock to return specific values when particular methods are called. In simple terms, "When the XYZ() method is called, then return ABC." It is mostly used when there is some condition to execute.
A mock does not call the real method, it is just proxy for actual implementations and used to track interactions with it. A spy is a partial mock, that calls the real methods unless the method is explicitly stubbed. Since Mockito does not mock final methods, so stubbing a final method for spying will not help.
In short, mocks are used as a replacement for a dependency. With Mockito, you create a mock, tell Mockito what to do when specific methods are called on it, and then use the mock instance in your test instead of the real thing.
To check if a method was called on a mocked object you can use the Mockito. verify method: Mockito. verify(someMock).
The short answer is that in your example, the result of mock.method()
will be a type-appropriate empty value; mockito uses indirection via proxying, method interception, and a shared instance of the MockingProgress
class in order to determine whether an invocation of a method on a mock is for stubbing or replay of an existing stubbed behavior rather than passing information about stubbing via the return value of a mocked method.
A mini-analysis in a couple of minutes looking at the mockito code is as follows. Note, this is a very rough description - there are a lot of details in play here. I suggest that you check out the source on github yourself.
First, when you mock a class using the mock
method of the Mockito
class, this is essentially what happens:
Mockito.mock
delegates to org.mockito.internal.MockitoCore
.mock, passing the default mock settings as a parameter.MockitoCore.mock
delegates to org.mockito.internal.util.MockUtil
.createMockMockUtil
class uses the ClassPathLoader
class to get an instance of MockMaker
to use to create the mock. By default, the CgLibMockMaker class is used.CgLibMockMaker
uses a class borrowed from JMock, ClassImposterizer
that handles creating the mock. The key pieces of the 'mockito magic' used are the MethodInterceptor
used to create the mock: the mockito MethodInterceptorFilter
, and a chain of MockHandler instances, including an instance of MockHandlerImpl. The method interceptor passes invocations to MockHandlerImpl instance, which implements the business logic that should be applied when a method is invoked on a mock (ie, searching to see if an answer is recorded already, determining if the invocation represents a new stub, etc. The default state is that if a stub is not already registered for the method being invoked, a type-appropriate empty value is returned.Now, let's look at the code in your example:
when(mock.method()).thenReturn(someValue)
Here is the order that this code will execute in:
mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn
The key to understanding what is going on is what happens when the method on the mock is invoked: the method interceptor is passed information about the method invocation, and delegates to its chain of MockHandler
instances, which eventually delegate to MockHandlerImpl#handle
. During MockHandlerImpl#handle
, the mock handler creates an instance of OngoingStubbingImpl
and passes it to the shared MockingProgress
instance.
When the when
method is invoked after the invocation of method()
, it delegates to MockitoCore.when
, which calls the stub()
method of the same class. This method unpacks the ongoing stubbing from the shared MockingProgress
instance that the mocked method()
invocation wrote into, and returns it. Then thenReturn
method is then called on the OngoingStubbing
instance.
The short answer is, behind the scenes, Mockito uses some kind of global variables/storage to save information of method stub building steps(invocation of method(), when(), thenReturn() in your example), so that eventually it can build up a map on what should be returned when what is called on what param.
I found this article very helpful: Explanation how proxy based Mock Frameworks work (http://blog.rseiler.at/2014/06/explanation-how-proxy-based-mock.html). The author implemented a demonstration Mocking framework, which I found a very good resource for people who want to figure out how these Mocking frameworks work.
In my opinion, it's a typical usage of Anti-Pattern. Normally we should avoid 'side effect' when we implement a method, meaning the method should accept input and do some calculation and return the result - nothing else changed besides that. But Mockito just violates that rule on purpose. Its methods store a bunch of info besides returning the result: Mockito.anyString(), mockInstance.method(), when(), thenReturn, they all have special 'side effect'. That's also why the framework looks like a magic at the first glance - we usually don't write code like that. However, in the mocking framework case, this anti-pattern design is a great design, since it leads to very simple API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With