Mockito with Spy

You work with legacy code. You want to add unit test for it.
You read this Basic unit test with Mockito and still don’t know how to apply with your legacy code.
Or you just want to see example of “spy” in Mockito.

Then, this page is for you.

Full Code

example2_spy_legacy_code.zip

What you need to run this:

  • Maven 3
  • Java 8

Let Try

Before reading this, you should know the “mock” concept in Mockito already. If not, read from here Basic unit test with Mockito.

Assume that you have a class named TransferMoneyService.  This class has its code like this.

The problem is that  depositeMoneyService and withdrawMoneyService are created by “new” inside the method.  These two classess have database call. They prevent you to create unit test. You need to create mocks for these two classes. You can change the method Parameter too look like this (so that you can create mock objects and pass in):

But this method is being used by too many places. So, you don’t want to change the API of this method. Otherwise you have to change all of the code which are using this method.

Our big question is “how can we mock the object if the object is created in the target method without changing method’s API?

The answer is that you can use “spy” in Mockito and minimize the change which will not change API. Let see how.

First, you “extract” the “new object” out to be a method. It will look like this:

Now you can use “spy” to change  proxyDepositMoneyServiceCreator  and proxyWithdrawMoneyServiceCreator to return mock objects. This is how the code looks like:

Let me explain:

These just mock. You should know that already.

This is “spy”. It creates a real object and mockito is spying it.  If you call target.transfer(…) ,the actual transfer() method will be called. It is different from this code:

From above code, if you call target.transfer(…) ,the actual transfer() method will NOT be called.

So, when you “spy”, the actual method will be called, also proxyDepositMoneyServiceCreator and proxyWithdrawMoneyServiceCreator. But we don’t want those two methods to be called.

Again, recall our big question? “how can we mock the object if the object is created in the target method without changing method’s API?”  The following code below is the answer, it changes proxyDepositMoneyServiceCreator and proxyWithdrawMoneyServiceCreator to return mock objects.

They mean when proxyDepositMoneyServiceCreator is called, it will return mockDepositMoneyService. Note that the syntax is different between doReturn() (in the above code) and thenReturn() in the code here  Basic unit test with Mockito . Why? It is Mockito’s rules.

Please look in the full code example here  example2_spy_legacy_code.zip

With this code:
– You can have unit test for Legacy code. This is the most important thing!!!
– You do not need to change API of your class !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">