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.

1. Mockito Introduction

Mockito is an open-source framework that allows us to easily create test doubles (mocks). A ‘test double‘ is a generic term for any case where we replace a production object for testing purposes.

In mockito, we generally work with the following kinds of test doubles.

  • Stubs – are objects that have predefined return values to the method executions made during the test.
  • Spies – are objects that are similar to stubs, but they additionally record the stats of how they were executed.
  • Mocks – are objects that have return values to method executions made during the test and has recorded expectations of these executions. Mocks can throw an exception if they receive a call they don’t expect and are checked during verification to ensure they got all the calls they were expecting.

We can mock both interfaces and classes in the test class. Mockito also helps to produce minimum boilerplate code if we use the using mockito annotations.

Once created, a mock will remember all interactions. Then we can selectively verify whatever interactions we are interested in.

2. Mockito Setup

2.1. Maven

To add mockito into the project, we can add the latest mockito version by any means i.e. Maven, Gradle or jar file.

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

2.2. Bootstrapping with JUnit

To process Mockito annotations with JUnit 5, we need to use MockitoExtention as follows:

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

For legacy JUnit 4, we can use either MockitoJUnitRunner or MockitoRule classes.

@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {
	//code
}
public class ApplicationTest {
	@Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

	//code
}

The strict stubbing ensures clean tests, reduces test code duplication, and improves debuggability. The test fails early when the code under test invokes a stubbed method with different arguments, or unused stubs are present.

Alternatively, we can programmatically bootstrap mockito using openMocks() method somewhere in the base class or a test runner. This method initializes fields annotated with Mockito annotations @Mock, @Spy, @Captor, @InjectMocks.

The previously used initMocks() method is now deprecated.

public class ApplicationTest {
	MockitoAnnotations.openMocks(this);
}

3. Mockito Annotations

Before hitting the keyboard to write unit tests, let’s quickly go through the useful mockito annotations.

  • @Mock is used for mock creation. It makes the test class more readable.
  • @Spy is used to create a spy instance. We can use it instead spy(Object) method.
  • @InjectMocks is used to instantiate the tested object automatically and inject all the @Mock or @Spy annotated field dependencies into it (if applicable). It is worth knowing the difference between @Mock and @InitMocks annotations.
  • @Captor is used to create an argument captor.
public class ApplicationTest {
  @Mock
  Depedency mock;

  @InjectMocks
  Service codeUnderTest;
}

4. Mockito Demo

4.1. System Under Test

To demo the Mockito syntax, we have created a typical usecase where a RecordService invokes RecordDao to save a Record.

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

4.2. Test Demo

  • To test RecordService.saveRecord() method, we need to inject RecordDao and SequenceGenerator as dependencies in it. For this, we are using @Mock and @InjectMocks annotations.
  • The @ExtendWith(MockitoExtension.class) starts the bootstrapping process and injects the mocks into the service instance.
  • We use the when(…).then(…) methods to record the expectations from mock objects, and we verify these expectations, after the application code execution finishes, using the verify() method calls.
  • Finally, we can use additional JUnit assertions for additional validations, if any.
@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

In this Mockito JUnit tutorial, we learned the basics of mocking and stubbing using the mockito framework. We learned to bootstrap the mocking process in JUnit 4 and 5 environments.

Finally, we saw an example of a test using mockito and junit.

Happy Learning !!

Sourcecode on Github

Leave a Reply

0 Comments
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.

Our Blogs

REST API Tutorial