Getting Started With Mockito and JUnit

In this mockito tutorial, learn the fundamentals of the mockito framework, and how to write JUnit tests along with mockito with an example.

Mockito

Mockito is a Java mocking framework that creates test doubles, which replace real dependencies in a unit test and record how the code under test calls them. We use Mockito with JUnit to test a class in isolation, for example a service without its database access class. In a Mockito test, we replace the database access class with a mock and verify the calls made to it. The following example injects a mock ItemRepository into ItemService with the annotations @Mock and @InjectMocks.

@ExtendWith(MockitoExtension.class)
public class ItemServiceTest {

  @Mock
  private ItemRepository itemRepository;

  @InjectMocks
  private ItemService itemService; // Assuming ItemService uses ItemRepository

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

1. Introduction to Mockito

Mockito is an open-source framework that creates test doubles (mocks). A test double is any object that replaces a production object in a test.

Mockito works with the following kinds of test doubles.

  • Stubs are objects with predefined return values for the method calls made during the test.
  • Spies are stubs that also record how they were called.
  • Mocks are objects with return values for the method calls made during the test, and with recorded expectations for these calls. A mock throws an exception when it receives an unexpected call, and verification checks that it received all the expected calls.

Mockito can mock both interfaces and classes in a test class. The Mockito annotations reduce the boilerplate code for creating the mocks.

Once created, a mock records all interactions, and the test verifies the interactions it needs.

2. Mockito Setup with JUnit

2.1. Maven

To add Mockito to the project, we add the latest Mockito version with Maven, Gradle or a jar file.

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.4.0</version>
    <scope>test</scope>
</dependency>
testCompile group: 'org.mockito', name: 'mockito-core', version: '4.6.1'

2.2. Bootstrapping with JUnit 5

To use Mockito with JUnit 5, add the JUnit Jupiter dependency.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>

To process the Mockito annotations with JUnit 5, we register the extension class MockitoExtension with @ExtendWith.

@ExtendWith(MockitoExtension.class)
public class ApplicationTest {
   //code
}

2.2. Bootstrapping with JUnit 4 [Legacy]

To use Mockito with JUnit 4, add the JUnit 4 dependency.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

JUnit 4 tests use either the runner class MockitoJUnitRunner or the rule class MockitoRule.

@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {
	//code
}
@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {

  @Rule 
  public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

  //code
}

Strict stubbing reduces duplicated test code and makes failures easier to debug. The test fails early when the code under test calls a stubbed method with different arguments, or when a stub is unused.

2.3. Programmatic Initialization

Alternatively, the method MockitoAnnotations.openMocks(), called in a base class or a test runner, initializes the fields annotated with @Mock, @Spy, @Captor and @InjectMocks.

The previously used initMocks() method is now deprecated.

@BeforeEach
public void setup() {

  MockitoAnnotations.openMocks(this);
}

3. Mockito Annotations

Mockito provides the following annotations for the test doubles.

  • @Mock creates a mock. It makes the test class more readable.
  • @Spy creates a spy instance and replaces the method spy(Object).
  • @InjectMocks creates an instance of the tested object and injects the fields annotated with @Mock or @Spy into it, where applicable. Read about the difference between @Mock and @InitMocks annotations.
  • @Captor creates an argument captor.
public class ApplicationTest {

  @Mock
  Depedency mock;

  @InjectMocks
  Service codeUnderTest;
}

4. Mockito Demo

4.1. System Under Test

The following example is a typical use case, in which the class RecordService calls the class RecordDao to save a Record.

The class RecordService uses the class SequenceGenerator to get the next record id.

4.2. Test Demo

  • To test the method RecordService.saveRecord(), we inject RecordDao and SequenceGenerator into it as dependencies with the annotations @Mock and @InjectMocks.
  • The annotation @ExtendWith(MockitoExtension.class) starts the bootstrapping and injects the mocks into the service instance.
  • The test records the expectations of the mock objects with the methods when(…).then(…) and verifies them after the application code runs with the method verify().
  • Additional JUnit assertions validate the rest of the result, if needed.
@ExtendWith(MockitoExtension.class)
public class MockitoHelloTest {

  @Mock
  RecordDao mockDao;

  @Mock
  NotificationService mockNotification;

  @Mock
  SequenceGenerator mockGenerator;

  @InjectMocks
  RecordService service;

  @Test
  public void testSaveRecord() {

    Record record = new Record();
    record.setName("Test Record");

    when(mockGenerator.getNext()).thenReturn(100L);
    when(mockDao.saveRecord(record)).thenReturn(record);

    Record savedRecord = service.saveRecord(record);

    verify(mockGenerator, times(1)).getNext();
    verify(mockDao, times(1)).saveRecord(any(Record.class));

    assertEquals("Test Record", savedRecord.getName());
    assertEquals(100L, savedRecord.getId());
  }
}

5. Conclusion

Mockito creates mocks and stubs that replace dependencies in JUnit tests. The extension class MockitoExtension initializes them in JUnit 5, and the runner and rule classes do the same in JUnit 4.

The demo test combines the annotations, the stubbing with when() and the verification with verify() in one test.

Happy Learning !!

Sourcecode on Github

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.