Introduction
With mockito, you can not only create mocks but also spies. A spy behaves the same as a real/normal instance of a class, but mockito tracks all the interactions that happen with the spy.
Create a spy with Mockito
You create a spy by calling the mockito.spy()
method with the instance you want to spy on as a parameter. In the following example,
I create a spy of the dog instance on line 6. Mockito can use the spy to track the interactions that happen with the instance.
In the example, the bark()
method is called and I can use the mockito.verify()
to check if this interaction has happened.
|
|
Create Spy for a final class
When you try to spy on a final class you get the following exception when you use the wrong mock maker:
|
|
This exception can be fixed by chancing the default mock maker. With Mockito 5 this is no longer needed as the default can create spies for final classes.
If you use mockito 4 you need to include the following dependency to use the mock maker inline. The mock maker inline is the new default mock maker starting with Mockito 5 and is able to mock and spy on final classes.
|
|
This dependency changes the default mock maker to the mock maker inline.
With the mocker maker inline enabled you can now spy on final classes like is done in the following example:
|
|
In the previous example a spy is created for the final class TheFinalDog.
Create a spy using @spy annotation
We can make the test more readable by using Mockito's annotation @Spy
. On lines 7 and 8 in the following example, I
create an instance and a spy of the Dog class on a single line. Inside the test method, I can directly use the spy.
Read this article if you want to know more about using Mockito's annotations with JUnit.
|
|
Alter behavior of a spy
You can also stub methods calls just as you do with mocks. In the following example, I use the spy of the dog instance to stub a method. On line 9, I stub the bark() method and make it return a different value than the original.
|
|
Difference with mocks
Mockito tracks the behavior of your objects when you either create a mock of a spy. The biggest difference lies in its default behavior. When you create a mock every call is stubbed and returns null by default and not calling any real object. When you create a spy every method by default calls the real instance.
Depending on the default behavior you need to choose whichever works best for your use case.
Conclusion
This post shows how to create a spy using an existing instance by calling the Mockito.spy method. to make the test more readable you can also use the annotation @spy to create a spy. The last example shows that you can stub method calls to a spy instance.
Further reading
More about testing in Java: