Reputation: 60778
This code from the documentation is totally baffling me:
List list = new LinkedList();
List spy = spy(list);
when(spy.size()).thenReturn(100); // <--- how does this spy know
// not to call the real method????
//using the spy calls *real* methods
spy.add("one");
spy.add("two");
I get it, Mockito is weird and hardly still in Java. Confusing thing is spy.*
has to evaluate fully before it knows whether it's wrapped in a when()
or something. How on earth would the first spy.*
method not call on the real object but the later ones doe?
Upvotes: 2
Views: 570
Reputation: 1499
According to the documentation the first when(spy.size()).thenReturn(100)
will actually invoke the real List.size()
method, see: http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html#13
Each subsequent call of course will then return the mocked result.
If you don't want the real method to be called (e.g. when(spy.get(0)).thenReturn(...)
would probably throw an IndexOutOfBoundsException
, you have to use this pattern: doReturn(...).when(spy).get(0);
Upvotes: 3
Reputation: 279970
I don't know the exact implementation, but I can take a guess.
The call to spy(...)
first proxies the given object and keeps it as a reference to delegate calls.
The call
when(spy.size()).thenReturn(100);
is practically equivalent to
Integer result = spy.size();
OngoingStubbing<Integer> stubbing = when(result); // result is useless
stubbing.thenReturn(100);
The first call to size()
is invoked on the proxy. Internally, it can register the call, pushing it, for example, on a static
(global) Mockito stack. When you then invoke when()
, Mockito pops from the stack, recognizes the call to size()
as needing stubbing and performs whatever logic required to do so.
This can explain why stubbing in a multithreaded environment is bad business.
Upvotes: 1