JUnit and Mockito in Spring Boot

JUnit and Mockito in Spring Boot

·

6 min read

As we all know, when it comes to development Unit testing is one of the major important practices to be maintained in application development.

In this article let us have a look at Junit and Mockito frameworks of Unit testing in Java applications for Rest apis.

The topic includes:

  1. What is UnitTesting?

  2. What is JUnit?

  3. What is the Mockito Framework?

  4. What is Mocking?

  5. Step By Step Implementation

What is UnitTesting?

Unit Testing is known as one of the continuous processes of Agile methodology. Unit testing comes into the picture at the developer's level. Unit testing is a type of software testing in which individual components of the software application are tested.

Consider you are writing a Rest API, so for each of the APIs, we can write the test cases and test in the application before committing to our main API. In unit testing, we will mock the services, which means we will not call the database every time instead we will use the mockup data.

What is JUnit?

JUnit is a unit testing framework for Java programming language. It plays a major role in test-driven development and is known as a family of Unit testing frameworks known as xUnit.

JUnit provides the developer with an idea of first testing and then coding so that we will be sure of what type of data is required before implementing the actual APIs.

Using JUnit increases the productivity of the programmer and maintains application stability.

Since JUnit is a framework for writing test cases, it provides annotations to identify the test methods and provides assertions for testing the expected results.

What is the Mockito Framework?

Mockito is a Java-based mocking framework used for unit testing of Java applications. Mockito was released as an open-source testing framework under the MIT License.

Mockito internally uses the Java reflection API to generate the mock objects. The main purpose of using the Mockito framework is to simplify development by mocking the external dependencies and using them in the test code. We can also use Mockito with other testing frameworks like JUnit and TestNG.

What is Mocking?

Mocking is the process of developing the objects that act as the mock or clone of objects. That is instead of using the real objects we will be using the mocked objects. Mock objects provide specific or dummy inputs and outputs.

Step By Step Implementation

Step 1: Create a Spring Boot application using Spring initialize and add the following dependencies.

  • Spring Web

  • Spring Data JPA

  • Lombok

Generate the Spring boot project as a zip file, extract it, and import it into the IDE

Step 2: Make sure that you have added the below dependencies in your spring boot project:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

Step 3: Create a JPA Entity

Now create an Employee JPA entity with the following content:

import lombok.*;

import javax.persistence.*;

@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder

@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "first_name", nullable = false)
    private String firstName;

    @Column(name = "last_name", nullable = false)
    private String lastName;

    @Column(nullable = false)
    private String email;
}

Note that we are using Lombok annotations to reduce the boilerplate code.

Step 4: Create Repository Layer

Now create EmployeeRepository which extends the JpaRepository interface:

import net.jUnitApplication.springboot.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}

Step 5: Create Service Layer

Create an EmployeeService interface with CRUD methods:

import net.jUnitApplication.springboot.model.Employee;

import java.util.List;
import java.util.Optional;

public interface EmployeeService {
    Employee saveEmployee(Employee employee);
    List<Employee> getAllEmployees();
    Optional<Employee> getEmployeeById(long id);
    Employee updateEmployee(Employee updatedEmployee);
    void deleteEmployee(long id);
}

Now create an EmployeeServiceImpl class that implements the EmployeeService interface:

import net.jUnitApplication.springboot.exception.ResourceNotFoundException;
import net.jUnitApplication.springboot.model.Employee;
import net.jUnitApplication.springboot.repository.EmployeeRepository;
import net.jUnitApplication.springboot.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    private EmployeeRepository employeeRepository;

    public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    @Override
    public Employee saveEmployee(Employee employee) {

        Optional<Employee> savedEmployee = employeeRepository.findByEmail(employee.getEmail());
        if(savedEmployee.isPresent()){
            throw new ResourceNotFoundException("Employee already exist with given email:" + employee.getEmail());
        }
        return employeeRepository.save(employee);
    }

    @Override
    public List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }

    @Override
    public Optional<Employee> getEmployeeById(long id) {
        return employeeRepository.findById(id);
    }

    @Override
    public Employee updateEmployee(Employee updatedEmployee) {
        return employeeRepository.save(updatedEmployee);
    }

    @Override
    public void deleteEmployee(long id) {
        employeeRepository.deleteById(id);
    }
}

Step 6: Unit Testing Service Layer using JUnit 5 and Mockito

Let us write the Unit test case for EmployeeService. We should be able to write unit tests for EmployeeService WITHOUT using any Spring features.

We will be creating a mock of EmployeeRepository using @Mock and create an EmployeeServiceImpl instance using the mock EmployeeRepository instance.

import net.jUnitApplication.springboot.exception.ResourceNotFoundException;
import net.jUnitApplication.springboot.model.Employee;
import net.jUnitApplication.springboot.repository.EmployeeRepository;
import net.jUnitApplication.springboot.service.impl.EmployeeServiceImpl;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willDoNothing;
import static org.mockito.Mockito.*;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

@ExtendWith(MockitoExtension.class)
public class EmployeeServiceTests {

    @Mock
    private EmployeeRepository employeeRepository;

    @InjectMocks
    private EmployeeServiceImpl employeeService;

    private Employee employee;

    @BeforeEach
    public void setup(){
        //employeeRepository = Mockito.mock(EmployeeRepository.class);
        //employeeService = new EmployeeServiceImpl(employeeRepository);
        employee = Employee.builder()
                .id(1L)
                .firstName("Ramesh")
                .lastName("Fadatare")
                .email("ramesh@gmail.com")
                .build();
    }

    // JUnit test for saveEmployee method
    @DisplayName("JUnit test for saveEmployee method")
    @Test
    public void givenEmployeeObject_whenSaveEmployee_thenReturnEmployeeObject(){
        // given - precondition or setup
        given(employeeRepository.findByEmail(employee.getEmail()))
                .willReturn(Optional.empty());

        given(employeeRepository.save(employee)).willReturn(employee);

        System.out.println(employeeRepository);
        System.out.println(employeeService);

        // when -  action or the behaviour that we are going test
        Employee savedEmployee = employeeService.saveEmployee(employee);

        System.out.println(savedEmployee);
        // then - verify the output
        assertThat(savedEmployee).isNotNull();
    }
}

JUnit test for getAllEmployees method

@DisplayName("JUnit test for getAllEmployees method")
    @Test
    public void givenEmployeesList_whenGetAllEmployees_thenReturnEmployeesList(){
        // given - precondition or setup

        Employee employee1 = Employee.builder()
                .id(2L)
                .firstName("Tony")
                .lastName("Stark")
                .email("tony@gmail.com")
                .build();

        given(employeeRepository.findAll()).willReturn(List.of(employee,employee1));

        // when -  action or the behaviour that we are going test
        List<Employee> employeeList = employeeService.getAllEmployees();

        // then - verify the output
        assertThat(employeeList).isNotNull();
        assertThat(employeeList.size()).isEqualTo(2);
    }

JUnit test for getEmployeeById method

@DisplayName("JUnit test for getEmployeeById method")
    @Test
    public void givenEmployeeId_whenGetEmployeeById_thenReturnEmployeeObject(){
        // given
        given(employeeRepository.findById(1L)).willReturn(Optional.of(employee));

        // when
        Employee savedEmployee = employeeService.getEmployeeById(employee.getId()).get();

        // then
        assertThat(savedEmployee).isNotNull();

    }

JUnit test for updateEmployee method

@DisplayName("JUnit test for updateEmployee method")
    @Test
    public void givenEmployeeObject_whenUpdateEmployee_thenReturnUpdatedEmployee(){
        // given - precondition or setup
        given(employeeRepository.save(employee)).willReturn(employee);
        employee.setEmail("ram@gmail.com");
        employee.setFirstName("Ram");
        // when -  action or the behaviour that we are going test
        Employee updatedEmployee = employeeService.updateEmployee(employee);

        // then - verify the output
        assertThat(updatedEmployee.getEmail()).isEqualTo("ram@gmail.com");
        assertThat(updatedEmployee.getFirstName()).isEqualTo("Ram");
    }

JUnit test for deleteEmployee method

@DisplayName("JUnit test for deleteEmployee method")
    @Test
    public void givenEmployeeId_whenDeleteEmployee_thenNothing(){
        // given - precondition or setup
        long employeeId = 1L;

        willDoNothing().given(employeeRepository).deleteById(employeeId);

        // when -  action or the behaviour that we are going test
        employeeService.deleteEmployee(employeeId);

        // then - verify the output
        verify(employeeRepository, times(1)).deleteById(employeeId);
    }

The above example code gives the CRUD operation testing of REST APIs using Junit and Mockito.

I hope this article is helpful. Thank you for reading the article. Please like, share and comment. It will encourage me to write more such articles. Do share your valuable suggestions, I appreciate your honest feedback!!!