Mockito – Difference between @Mock and @InjectMocks annotations

During unit testing with junit and mockito, we use @Mock and @InjectMocks annotations to create objects and dependencies to be tested. Learn the difference between @Mock and @InjectMocks annotations in mockito.

1. Difference between Mock vs Stub Object

It is important to understand the difference between a mock and an object. An object is an actual instance of a class and any method invoked using object reference will execute the method body defined in the class file.

A mock object is an interface to hide a dependency with cannot be tested in test environment e.g. database, network locations etc. A method invoked using mocked reference does not execute method body defined in class file, rather the method behavior is configured using when-thenReturn methods combinations.

In a junit test, we create objects for the class which needs to be tested and it’s methods to be invoked. We create mocks for the dependencies which will not be present in test environment and objects are dependent on it to complete the method call.

2. Difference between @Mock and @InjectMocks

In mockito based junit tests, @Mock annotation creates mocks and @InjectMocks creates class objects.

@Mock – creates mocks
@InjectMocks – creates objects and inject mocked dependencies

  • Use @InjectMocks to create class instances which needs to be tested in test class.
  • Use @InjectMocks when actual method body needs to be executed for a given class.
  • Use @InjectMocks when we need all internal dependencies initialized with mock objects to work method correctly.
  • Use @Mock to create mocks which are needed to support testing of class to be tested.
  • Annotated class (to be tested) dependencies with @Mock annotation.
  • We must define the when-thenRetrun methods for mock objects which class methods will be invoking during actual test execution.

3. @Mock and @InjectMocks Example

Let’s understand the difference between @Mock and @InjectMocks with an example. In this example, we have class MainClass which has a method save().

MainClass has a dependency on DatabaseDAO and NetworkDAO. When we call MainClass.save() method, it internally calls save methods of both dependent objects.

3.1. Java classes

public class MainClass {
	
	DatabaseDAO database;
	NetworkDAO network;
	
	//Setters and getters

	public boolean save(String fileName) 
	{
		database.save(fileName);
		System.out.println("Saved in database in Main class");
		
		network.save(fileName);
		System.out.println("Saved in network in Main class");
		
		return true;
	}
}
public class DatabaseDAO {
	public void save(String fileName) {
		System.out.println("Saved in database");
	}
}
public class NetworkDAO {
	public void save(String fileName) {
		System.out.println("Saved in network location");
	}
}

3.2. Junit test for MainClass

Let’s write junit test for MainClass.

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class ApplicationTest 
{
	@InjectMocks
	MainClass mainClass;
	
	@Mock
	DatabaseDAO dependentClassOne;
	
	@Mock
	NetworkDAO dependentClassTwo;
	
	@Before
	public void init() {
		MockitoAnnotations.initMocks(this);
	}
	
	@Test
	public void validateTest()
	{
		boolean saved = mainClass.save("temp.txt");
		assertEquals(true, saved);
	}
}

The test is executed successfully and we get below statements printed in console. Watch the console output very carefully.

Saved in database in Main class
Saved in network in Main class

In above test, statements are printed which are written in MainClass.save() method, but not for dependent classes. It proves that method body was executed for only MainClass’s save() method because we created the actual object of MainClass using @InjectMocks annotation. For dependent classes, we used mocks.

3.3. Verify method invocations on mocks

To verify that mock methods has been invoked, we must use mockito provided utility method verify(). It helps in verifying that mock methods has been executed while executing the actual test class method.

@Test
public void validateTest()
{
	boolean saved = mainClass.save("temp.txt");
	assertEquals(true, saved);
	
	verify(dependentClassOne, times(1)).save("temp.txt");
	verify(dependentClassTwo, times(1)).save("temp.txt");
}

4. Conclusion

In this mockito tutorial, we learned the difference between @Mock and @InjectMocks annotations. We learned what happen when we apply these annotation to classes in junit tests.

Happy Learning !!

References: Mockito Guide

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

2 thoughts on “Mockito – Difference between @Mock and @InjectMocks annotations”

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.