Getting Started with Mockito @Mock and @InjectMocks

This tutorial will teach you how to enable Mockito framework in your Spring Boot project and in addition to that, you will also learn how to use @Mock and @InjectMocks annotations to create mock objects and inject those mock objects into the class under test.

Spring Boot Support for Mockito

The good news is that Spring Boot provides excellent support for Mockito framework. The only dependency that you need to add to your Spring Boot project to start using Mockito framework is spring-boot-starter-test.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

The above Spring Boot Starter Test dependency will contain support for the following two dependencies:

  • mockito-core which is Mockito’s mock objects library core API and implementation, and
  • mockito-junit-jupiter which is Mockito’s JUnit 5 support.

Enable Mockito in Test Class

To start using Mockito annotations, you need to annotate your Test class with @ExtendWith(MockitoExtension.class) annotation.

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

   // Some code 


}

The @ExtendWith annotation is used to extend JUnit 5 with third-party extensions. In this example, we use @ExtendWith annotation to register MockitoExtention for our Test class and extend JUnit 5 API with additional functionality that Mockito framework provides.

Now that we have enabled Mockito in our Test class, we can start creating Mock objects.

@Mock Annotation

The @Mock annotation is used to create a Mock object. To do that, you will simply annotate the class member variable with @Mock annotation. Let’s have a look at an example below.

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
 
    @Mock
    UsersRepository usersRepository;

    @Mock
    EmailVerificationServiceImpl emailVerificationService;

    // Other code

}

Notice that in the code example above, the UsersRepository and EmailVerificationServiceImpl member variables are annotated with @Mock annotation. When this Test class executes, MockitoExtension will find all member variables annotated with @Mock annotation and it will create a mock implementation for them. These mock objects will then need to be further configured and injected into the method under test.

Inject Mock objects with @InjectMocks Annotation

The @InjectMocks annotation is used to inject mock objects into the class under test. This dependency injection can take place using either constructor-based dependency injection or field-based dependency injection for example. Let’s have a look at an example.

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @InjectMocks
    UserServiceImpl userService;

    @Mock
    UsersRepository usersRepository;

    @Mock
    EmailVerificationServiceImpl emailVerificationService;

    String firstName;
    String lastName;
    String email;
    String password;
    String repeatPassword;

    @BeforeEach
    void init() {
        firstName = "Sergey";
        lastName  = "Kargopolov";
        email = "[email protected]";
        password = "12345678";
        repeatPassword = "12345678";
    }

    @DisplayName("User object created")
    @Test
    void testCreateUser_whenUserDetailsProvided_returnsUserObject() {
        // Arrange
        Mockito.when(usersRepository.save(any(User.class))).thenReturn(true);

        // Act
        User user = userService.createUser(firstName, lastName, email, password, repeatPassword);

        // Assert
        assertNotNull(user, "The createUser() should not have returned null");
        assertEquals(firstName, user.getFirstName(), "User's first name is incorrect.");
        assertEquals(lastName, user.getLastName(), "User's last name is incorrect");
        assertEquals(email, user.getEmail(), "User's email is incorrect");
        assertNotNull(user.getId(), "User id is missing");
        Mockito.verify(usersRepository)
                .save(any(User.class));
    }

}

Notice that in the code example above, the userService member variable is annotated with @InjectMocks annotation. This means that UserServiceImpl is our class under test. So, when this Test class executes, MockitoExtension will do the following:

  1. Find all member variables annotated with @Mock annotation, and create a mock implementation of them,
  2. Find member variable annotated with @InjectMocks annotation and create a new instance of its class,
  3. Inject mock objects created with @Mock annotation into the class under test using dependency injection.

Also, for this to work the constructor of UserServiceImpl class will need to look like in the code example below:

public class UserServiceImpl implements UserService {

    UsersRepository usersRepository;
    EmailVerificationService emailVerificationService;

    public UserServiceImpl(UsersRepository usersRepository,
                           EmailVerificationService emailVerificationService) {
        this.usersRepository = usersRepository;
        this.emailVerificationService = emailVerificationService;
    }


 // other code
}

 

Configure Mock Object

Instead of calling a real method on the mock object, you will most likely want to configure it with different, pre-defined behaviour. Configuring a real method with temporary, predefined behaviour is called method stubbing. So, to stub a mock object with a predefined behaviour you will use Mockto’s when().thenReturn() or when().thenThrow() method chain.

In the code example above we use Mockito’s when().thenReturn() method chain to make the save() method always return a boolean value true.

// Arrange 
Mockito.when(usersRepository.save(any(User.class))).thenReturn(true);

Video lessons

I hope this tutorial was of some value to you. If you like learning by watching a series of step-by-step video lessons then have a look at my video course called “Testing Java with JUnit and Mockito“. This video course is for absolute beginners and you do not need to have any prior knowledge of testing Java applications to enrol.

Happy learning!