Recap and Slides
Today we talked about designing an app. Here are the slides:
One of the questions that came up was how does Mockito do its magic. The
specific point was in an example like this one:
Random mockRandom = mock(Random.class);
int nextInt = 5;
when(mockRandom.nextInt()).thenReturn(nextInt);
How does Mockito take an int and apply thenReturn()
successfully? In other
words, say that you break down the above example to the following. How crazy
does this look, when really this is exactly what you are doing?
Random mockRandom = mock(Random.class);
int nextInt = 5;
int originalAnswer = mockRandom.nextInt();
when(originalAnswer).thenReturn(nextInt);
I.e. you are basically saying when(5).thenReturn(nextInt)
, which makes no
sense at all unless you consider the lines around it. I believe the way this
works is that when you call a method on a mock, it obeys previously determined
behavior (e.g. it returns the value you told it to return), or it flags
that stubbing has begun, and it will error if stubbing has not completed. Two
examples. The code above, with the when(5)
example, does succeed and behaves
as expected, as the first example. This code, however, will fail with a
MissingMethodInvocationException
error. Clearly Mockito is tracking your
stubbing progress, since you haven’t called any methods on the mock yet.
Random mockRandom = mock(Random.class);
int nextInt = 5;
int originalAnswer = 5;
when(originalAnswer).thenReturn(nextInt);
// Crash due to MissingMethodInvocationException
This code, meanwhile, will fail since we’ve begun stubbing with an invocation
of a method on the mock class (the call to mockRandom.nextInt()
) and called
when()
, but we haven’t called thenReturn()
or similar. It will fail with an
UnfinishedStubbingException
.
Random mockRandom = mock(Random.class);
int nextInt = 5;
int originalAnswer = mockRandom.nextInt();
when(originalAnswer);
// Crash due to UnfinishedStubbingException
So, calling a method on a mock seems to flag that, if stubbing is initiated
with a call to when()
, the last called method is the one we want to save an
answer for. Once that is begun via the call to when()
, it must be completed
via a call to thenReturn()
or a similar method.
If you want to dive real deep down the rabbit hole, take a look at the
implementation
of the when
method on github.
Links