Mockito

Spring Test Mock Example

A unit test should test a class in isolation. Side effects from other classes or the system should be eliminated if possible. Mockito lets you write beautiful tests with a clean & simple API. In this example we will learn how to mock spring components using Mockito. Tools and technologies used in this example are Java 1.8, Eclipse Luna 4.4.2

1. Introduction

Mockito is a popular mocking framework which can be used in conjunction with JUnit. Mockito allows us to create and configure mock objects. Using Mockito simplifies the development of tests for classes with external dependencies significantly. We can create the mock objects manually or can use the mocking framewors like Mockito, EasyMock. jMock etc. Mock frameworks allow us to create mock objects at runtime and define their behavior. The classical example for a mock object is a data provider. In production a real database is used, but for testing a mock object simulates the database and ensures that the test conditions are always the same.

The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications – on any kind of deployment platform.

Be able to unit test spring components without the need of loading the full spring-context is a very useful behavior provided by Mockito.

2. Creating a project

Below are the steps we need to take to create the project.

  1. Open Eclipse. Go to File=>New=>Java Project. In the ‘Project name’ enter ‘SpringTestMock’.
  2. Eclipse will create a ‘src’ folder. Right click on the ‘src’ folder and choose New=>Package. In the ‘Name’ text-box enter ‘com.javacodegeeks’. Click ‘Finish’.

2.1 Dependencies

For this example we need the below mentioned jars:

  • junit-4.1.2
  • mockito-all-1.10.19
  • spring-beans-4.2.5.RELEASE
  • spring-context-4.2.5.RELEASE

These jars can be downloaded from Maven repository. These are the latest (non-beta) versions available as per now. To add these jars in the classpath right click on the project and choose Build Path=>Configure Build Path. The click on the ‘Add External JARs’ button on the right hand side. Then go to the location where you have downloaded these jars. Then click ok.

Figure 1. Dependencies
Figure 1. Dependencies

3. Code

To show how to use Mockito for mocking the Spring components we will use the User maintenance example. We will create a service class (UserMaintenanceService) with one method. This class will call the corresponding Data Access Object (DAO) to serve the request. First we will create a simple POJO class which represents the User domain entity.

User.java

package com.javacodegeeks;

import java.util.Date;

/**
* Class representing the user domain.
* @author Meraj
*/
public class User {

  private Long userId;
  private String firstName;
  private String surname;
  private Date dateOfBirth;

  public Long getUserId() {
    return userId;
  }

  public void setUserId(Long userId) {
    this.userId = userId;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getSurname() {
    return surname;
  }

  public void setSurname(String surname) {
    this.surname = surname;
  }

  public Date getDateOfBirth() {
    return dateOfBirth;
  }

  public void setDateOfBirth(Date dateOfBirth) {
    this.dateOfBirth = dateOfBirth;
  }
}

Now we will see how the DAO class looks like. The DAO class will be responsible for talking to the database. We will skip that part for this example. This class will be annotated as @Component. Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning

UserDao.java

package com.javacodegeeks;

import org.springframework.stereotype.Component;

/**
* DAO class for User related actions.
* @author Meraj
*/
@Component
public class UserDao {

  /**
  * Search for user using the id.
  * @param id user id
  * @return Retrieved user
  */
  public User findUserById(Long id) {
    // Find user details from database
    return new User();
  }
}

Now we will see how the service class looks like. This class will also be annotated with @Component. It has the reference to the UserDao class which it injects using the @Autowired annotation.

Autowire marks a constructor, field, setter method or config method as to be autowired by Spring’s dependency injection facilities. Only one constructor (at max) of any given bean class may carry this annotation, indicating the constructor to autowire when used as a Spring bean. Such a constructor does not have to be public. Fields are injected right after construction of a bean, before any config methods are invoked. Such a config field does not have to be public. Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container. Bean property setter methods are effectively just a special case of such a general config method. Such config methods do not have to be public.

UserMaintenanceService.java

package com.javacodegeeks;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* Service class for User related actions.
* @author Meraj
*/
@Component
public class UserMaintenanceService {

  @Autowired private UserDao userDao;

  /**
  * Find user.
  * @param userId user id
  * @return Retrieved user
  */
  public User findUserById(Long userId) {
  // Do business validations.
    return userDao.findUserById(userId);
  }
}

4. Test

Below is the test class which we will use to test in this example.

UserMaintenanceServiceTest.java

package com.javacodegeeks;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.util.Date;

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

public class UserMaintenanceServiceTest {

  @InjectMocks private UserMaintenanceService userMaintenanceService;
  @Mock private UserDao userDao;

  @Test
  public void testFindUserByIdPositive() {
    initMocks(this);
    when(userDao.findUserById(1000L)).thenReturn(getMeTestUser());
    User user = userMaintenanceService.findUserById(1000L);
    assertNotNull(user);
    assertEquals("Test first name", user.getFirstName());
    assertEquals("Test surname", user.getSurname());
  }

  @Test (expected = NullPointerException.class)
  public void testFindUserByIdNegetive() {
    userMaintenanceService = new UserMaintenanceService();
    userMaintenanceService.findUserById(1000L);
    fail();
}

  private User getMeTestUser() {
    User user = new User();
    user.setUserId(1000L);
    user.setFirstName("Test first name");
    user.setSurname("Test surname");
    user.setDateOfBirth(new Date());
    return user;
  }
}

Now we will discuss few things in this class. If you would have notice you will see that the UserMaintenanceService class is annotated with @InjectMocks. This marks a field on which injection should be performed. It minimizes repetitive mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won’t report failure; i.e. you will have to provide dependencies yourself.

  1. Constructor injection: the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. NoteIf arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won’t happen. In these cases, you will have to satisfy dependencies yourself.
  2. Property setter injection: mocks will first be resolved by type, then, if there is several property of the same type, by the match of the property name and the mock name. NoteIf you have properties with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.
  3. Field injection mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name. NoteIf you have fields with the same type (or same erasure), it’s better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won’t happen. If @InjectMocks instance wasn’t initialized before and have a no-arg constructor, then it will be initialized with this constructor.

The UserDao class is annotated with @Mock. This is the class which we want to mock.

In the first test method the first thing we do is call the MockitoAnnotations.initMocks() method. It initializes objects annotated with @Mock for given test class. Then we define the behaviour of the DAO class method by using the org.mockito.Mockito.when(). We return our own test User object here.

In the second test we are not calling the MockitoAnnotations.initMocks() so the DAO class will not be injected in this case hence it will throw NullPointerException.

5. Download the source file

This was an example of mocking spring components.

Download
You can download the full source code of this example here: SpringTestMock

Mohammad Meraj Zia

Senior Java Developer
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button