2

I know I don't really need to know how Mockito does everything under the hood in order to be able to use it, but this has been perplexing me for a while so more than anything I'm curious to understand it. There are several Mockito methods that I can't understand how they could possibly work. One good example is:

OngoingStubbing<T> Mockito.when(T methodCall)

You can use this to do things like:

Object mockedObject = Mockito.mock(Object.class);
Mockito.when(mockedObject.toString()).thenReturn("super cool string");
System.out.println(mockedObject.toString());

This code would give the output:

super cool string

I understand how to use this, but I don't understand how this could possibly work. How does Mockito.when know what mock object and method we are concerned with? As far as I know, we aren't passing in mockedObject, we are passing in mockedObject.toString() which is a value of type String. I'm pretty sure that prior to setting up all of the "when/thenReturn" stuff, mockedObject.toString() just returns null. So why isn't this the same as doing:

Object mockedObject = Mockito.mock(Object.class);
mockedObject.toString();
Mockito.when(null).thenReturn("super cool string");
System.out.println(mockedObject.toString());

Obviously the second code segment doesn't make any sense, but it seems like the two code segments should be functionally equivalent.

EDIT: The two code segments actually are the same. See my answer to my own question below.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
NateW
  • 908
  • 1
  • 8
  • 28

1 Answers1

2

Doh!

I guess I should have actually tried to run my sample code before I posted this question.

It turns out that the two code segments actually are equivalent. I just assumed that they weren't.

This revelation sheds some light into how Mockito.when is implemented under the hood.

My best guess now, is that when mockedObject is mocked, part of the newly created implementation of Object.toString() records that the .toString() method was called (this has to be done anyway in order to get Mockito.verify() to work). It must then record this call to a mock method in some sort of thread local static variable. Then when I call when(), it actually ignores the input value (except perhaps for using its type?) and then searches for whatever mocked method was most recently called on any of the mock objects that exist in that thread (or perhaps only the method calls that match that signature). Whatever method was last called is the one that it decides to modify.

This of course just my guesses based on how I've observed mockito's functionality. The actual implementation may be different, but this at least makes sense.

NateW
  • 908
  • 1
  • 8
  • 28