Mockito is a framework created for mocking objects for unit tests in mind. In this article, we are going to present how to use Mockito @Spy annotation to create wrapped objects whose behavior is tracked and could be verified in tests.
2. Initialize Mockito annotations
To activate Mockito annotations we need to use one of three given solutions:
- add @RunWith(MockitoJUnitRunner.class) at the top of unit test class,
- call MockitoAnnotations.initMocks(this) method in the @Before method of unit test class,
- use MockitoJUnit.rule() to create MockitoRule class.
3. Using spies in Mockito
@Spy annotation is used to wrap real objects and add a tracking mechanism for its method calls and value initializations. Spied instances work exactly in the same way as original ones unless specified otherwise. We can always configure the behavior of a spied object method using the same
when(...).then(...) syntax we would use with mock instances.
Let's check a simple example of a JUnit test with a spied object:
In this example:
@Spy private final List<String> list = new ArrayList<>();- defined a spied instance of
list.add("one"); list.add("two");- we are making some operations on the spied object (every call is tracked by Mockito),
verify()method on the mock object is used here to verify that the specified conditions are met,
verify(list).add("one");- we are checking if method
addwas called with
"one"String as a parameter,
verify(list).add("two");- we are checking if method
addwas called with
"two"String as an input parameter,
Assert.assertEquals(2, list.size());- this assertion proves that
addmethod was called on the "real" instance.
The same example but using Mockito.spy(...) method could be as follows:
4. Stubbing a Spy
We can configure spied objects in such a way that the selected methods return a specific value this operation is called stubbing.
Let's check an example of a stubbed object in the test:
In this example:
when(list.size()).thenReturn(100);- we are overrided original
Listtype, and configure it to return
100instead of the real list size,
Assert.assertEquals(100, list.size());- assertion on
list.size()now compare the size with 100.
5. Difference between @Mock and @Spy in Mockito
Mock objects replace completely mocked class. The mocked object will be returning configured or default values. We can create a mock out of the interface. Mocked objects do not have to be an instance.
Spying is when we take an existing instance and override only some or none methods. This type is useful when we want to mock just a few methods from a huge class. When you use the spy then the real methods are called (unless a method was stubbed).
Note that Mockito warns that partial mocking isn't a good practice. Spy (or partial mocking) is recommended to test legacy code.
Let's check a simple example with a mocked object:
As you can see added a single value to the mocked list doesn't change it at all. The size of the list is still 0.
Now let's see this example with spied instance:
When we called the
add(...) method on the spied object and this method was not configured with
when(...).then(...) syntax, the real implementation will be called. As a result, the size of the list will be 1.
In this article, we presented Mockito @Spy annotation. We show several examples of how to use it in JUnit tests and what is the difference between spied and mocked objects.
All code snippets used in this article, are available under the GitHub repository.