Mockito annotations – @Mock, @Spy, @Captor, @InjectMocks

In this mockito tutorial, learn about mockito annotations such as @Mock, @Spy, @Captor, @InjectMocks. Learn to write unit tests for behavior testing using mockito annotations.

1. Mockito annotations

1.1. @Mock

The @Mock annotation is used to create and inject mocked instances. We do not create real objects, rather ask mockito to create a mock for the class.

The @Mock annotation is alternative to Mockito.mock(classToMock). They both achieve the same result. Using @Mock is usually considered “cleaner“, as we don’t fill up the tests with boilerplate assignments that all look the same.

Using the @Mock annotation –

  • allows shorthand creation of objects required for testing.
  • minimizes repetitive mock creation code.
  • makes the test class more readable.
  • makes the verification error easier to read because field name is used to identify the mock.

In given example, we have mocked the HashMap class. In real tests, we shall be mocking actual application classes. We put a key-value pair in map, and then verified that method invocation was performed on mocked map instance.

@Mock
HashMap<String, Integer> mockHashMap;

@Test
public void saveTest()
{
	mockHashMap.put("A", 1);
	
	Mockito.verify(mockHashMap, times(1)).put("A", 1);
	Mockito.verify(mockHashMap, times(0)).get("A");

	assertEquals(0, mockHashMap.size());
}

1.2. @Spy

The @Spy annotation is used to create a real object and spy on that real object. A spy helps to call all the normal methods of the object while still tracking every interaction, just as we would with a mock.

Notice in given example, how the size of map is maintained to 1 because we added one key-value pair to it. We are also able to get back the value added to map using it’s key. It is not possible in mocked instances.

@Spy
HashMap<String, Integer> hashMap;

@Test
public void saveTest()
{
	hashMap.put("A", 10);
	
	Mockito.verify(hashMap, times(1)).put("A", 10);
	Mockito.verify(hashMap, times(0)).get("A");
	
	assertEquals(1, hashMap.size());
	assertEquals(new Integer(10), (Integer) hashMap.get("A"));
}
Difference between @Mock and @Spy

When using @Mock, mockito creates a bare-bones shell instance of the Class, entirely instrumented to track interactions with it. This is not a real object and does not maintain the state changes to it.

When using @Spy, mockito creates a real instance of the class and track every interactions with it. It maintains the state changes to it.

1.3. @Captor

The @Captor annotation is used to create an ArgumentCaptor instance which is used to capture method argument values for further assertions.

Note that mockito verifies argument values using the equals() method of argument class.

@Mock
HashMap<String, Integer> hashMap;

@Captor
ArgumentCaptor<String> keyCaptor;

@Captor
ArgumentCaptor<Integer> valueCaptor;

@Test
public void saveTest() 
{
	hashMap.put("A", 10);

	Mockito.verify(hashMap).put(keyCaptor.capture(), valueCaptor.capture());

	assertEquals("A", keyCaptor.getValue());
	assertEquals(new Integer(10), valueCaptor.getValue());
}

1.4. @InjectMocks

In mockito, we need to create the object of class to be tested and than insert it’s dependencies (mocked) to completely test the behavior. To do this, we use @InjectMocks annotation.

@InjectMocks marks a field on which injection should be performed. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection – in this order. If any of the given injection strategy fail, then Mockito won’t report failure.

Read More : Difference between @Mock and @InitMocks annotations

2. How to initialize mockito annotations

In order to use above annotations, the test class should initialize the annotation using one of three given ways:

  1. Use @RunWith(MockitoJUnitRunner.class) at the top of unit test class.
    @RunWith(MockitoJUnitRunner.class)
    public class ExampleTest {
    
        @Mock
        private List list;
    
        @Test
        public void shouldDoSomething() {
            list.add(100);
        }
    }
    
  2. Use MockitoAnnotations.initMocks(this) in the @Before method of unit test class.
    public class ExampleTest {
    
        @Mock
        private List list;
    
        @Before
        public void setup() {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void shouldDoSomething() {
            list.add(100);
        }
    }
    
  3. Use MockitoJUnit.rule() to create MockitoRule class.
    public class ExampleTest {
    
        @Rule
        public MockitoRule rule = MockitoJUnit.rule();
    
        @Mock
        private List list;
    
        @Test
        public void shouldDoSomething() {
            list.add(100);
        }
    }
    

Drop me your questions related to mockito annotations in comments.

Happy Learning !!

References:

Mock Java Doc
Spy Java Doc
Captor Java Doc
InjectMocks Java Doc

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

2 thoughts on “Mockito annotations – @Mock, @Spy, @Captor, @InjectMocks”

  1. Hi,
    I need to know, how I can inject real object with mocked object to a service in test case. Is it possible to do so?

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and related technologies, the best practices, algorithms, and interview questions.