Mockito Initialization with @Mock vs @InjectMocks

During unit testing with junit and mockito, generally, we use @Mock and @InjectMocks annotations to create mocks and SUT (System Under Test) to be tested. In this tutorial, we will learn the difference between @Mock and @InjectMocks annotations in mockito.

@ExtendWith(MockitoExtension.class)
public class ItemServiceTest {

  @Mock
  private ItemRepository itemRepository;

  @InjectMocks
  private ItemService itemService;   // ItemService uses ItemRepository

  @Test
  public void testCreateItem() {
      
      // ...
    }
}

1. What is a Mock?

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 a proxy interface to hide an underlying dependency that cannot be tested in a test environment e.g. database, network locations etc. A method invoked using mocked reference does not execute the actual method body defined in the class file, rather the method behavior is configured using when(...).thenReturn(...) methods.

  • In a junit test, we create objects for the class that need to be tested and its methods to be invoked.
  • We create mocks for the dependencies which will not be present in the 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 actual objects and injects mocked dependencies into it.

  • Use @InjectMocks to create class instances that need to be tested in the test class. We call it ‘code under test‘ or ‘system under test‘.
  • Use @InjectMocks when the actual method body needs to be executed for a given class.
  • Use @InjectMocks when we need all or a few internal dependencies initialized with mock objects to work the method correctly.
  • Use @Mock to create mocks that are needed to support the testing of SUT.
  • We must define the when(...).thenReturn(...) methods for mock objects whose class methods will be invoked during actual test execution.

3. Demo

Let’s understand the difference between @Mock and @InjectMocks with an example. In this example, we have a class MainClass that 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. System Under Test

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 boolean save(String fileName) {
		System.out.println("Saved in database");
		return true;
	}
}
public class NetworkDAO {
	public void save(String fileName) {
		System.out.println("Saved in network location");
		return true;
	}
}

3.2. Unit Test

Let’s write the 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.openMocks(this);
	}

	@Test
	public void validateTest()
	{
		//record expectations with mock methods
		when(dependentClassOne.save()).thenReturn(true);
		when(dependentClassTwo.save()).thenReturn(true);

		boolean saved = mainClass.save("temp.txt");
		assertEquals(true, saved);

		//verify recorded expectations
	}
}

4. Conclusion

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

Happy Learning !!

Comments

Subscribe
Notify of
guest
8 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.