How To Unittest Spring Boot Service Layer
Spring Boot Unit Testing Service Layer using JUnit and Mockito
In the previous tutorial, we have seen Spring Kicking Unit Testing CRUD Rest API with JUnit and Mockito. In this tutorial, nosotros will larn how toperform unit testing Spring boot service layer unit testing using JUnit 5 and the Mockito framework.
In order to examination Service layer components, nosotros accept to mock the Repository layer components using the Mockito framework. We don't take to utilize a database for Unit testing.
Check out my Leap boot testing Udemy course: Testing Spring Boot Application with JUnit and Mockito (Includes Testcontainers)
Spring kicking providesbound-boot-starter-exam dependency for unit of measurement testing and integration testing of Spring kick application:
<dependency> <groupId>org.springframework.kicking</groupId> <artifactId>jump-boot-starter-test</artifactId> <scope>test</telescopic> </dependency> The Spring Boot Starter Test dependency is a primary dependency for testing the Leap Kick Applications. It holds all the necessary elements required for the testing.
For the Unit testing service layer, we are going to use the following testing libraries:
- JUnit five Framework
- Mockito 4 (Latest)
- AssertJ Library
JUnit five Framework
It's the de facto standard testing framework for Java.
The current version of JUnit is 5+. The main goal of JUnit v is to support Java viii and above, as well as enable many different styles of testing.
Mockito iv (Latest)
Mockito is a mocking framework. It is a Java-based library used to create elementary and basic test APIs for performing unit of measurement testing of Java applications.
The main purpose of using the Mockito framework is to simplify the development of a test past mocking external dependencies and using them in the test code.
AssertJ Library
AssertJ is a Java library that provides a rich set of assertions and truly helpful error messages, improves test lawmaking readability, and is designed to be super like shooting fish in a barrel to utilise within your favorite IDE.
Spring boot starter exam dependency internally providesassertj-core dependency and so we don't accept to addassertj-core dependency manually in our Spring boot project.
Tools and technologies used
- Java eleven+
- Spring Boot
- Lombok
- JUnit 5 Framework
- Hamcrest
- AssertJ
- JsonPath
- Mockito
- IntelliJ Idea
- Docker
- Maven
ane. Create Spring Boot Application
Using leap initialize, create a Leap Kick project and add the following dependencies:
- Spring Web
- Spring Data JPA
- Lombok
Generate the Jump kick project as a zip file, extract it, and import it into IntelliJ Idea.
2. Maven Dependencies
Make certain that y'all have added the below dependencies in your spring boot projection:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>jump-kicking-starter-information-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-kicking-starter-test</artifactId> <scope>test</scope> </dependency> three. Create JPA Entity
Next, let's create anEmployee JPA entity with the following content:
import lombok.*; import javax.persistence.*; @Setter @Getter @AllArgsConstructor @NoArgsConstructor @Builder @Entity @Table (name = "employees" ) public grade Employee { @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private long id; @Cavalcade (proper noun = "first_name" , nullable = false ) private String firstName; @Column (name = "last_name" , nullable = false ) private String lastName; @Column (nullable = simulated ) private String email; }
Note that we are using Lombok annotations to reduce the boilerplate code.
@Entity annotation is used to marking the class as a persistent Java class.
@Tabular array annotation is used to provide the details of the table that this entity volition be mapped to.
@Id annotation is used to define the principal primal.
@GeneratedValue annotation is used to define the master fundamental generation strategy. In the above example, we have declared the primary key to be an Auto Increase field.
@Column note is used to define the properties of the column that will be mapped to the annotated field. Yous can define several properties like name, length, nullable, updateable, etc.
4. Create Repository Layer
Let's create EmployeeRepository which extends the JpaRepository interface:
import net .javaguides .springboot .model .Employee ; import org .springframework .data .jpa .repository .JpaRepository ; public interface EmployeeRepository extends JpaRepository < Employee , Long > { } 5. Create Service Layer
EmployeeService
Let's create anEmployeeService interface with CRUD methods:
import net.javaguides.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) ; } EmployeeServiceImpl
Permit's create anEmployeeServiceImpl class that implements theEmployeeService interface:
import cyberspace.javaguides.springboot.exception.ResourceNotFoundException; import net.javaguides.springboot.model.Employee; import cyberspace.javaguides.springboot.repository.EmployeeRepository; import net.javaguides.springboot.service.EmployeeService; import org.springframework.beans.factory.notation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class EmployeeServiceImpl implements EmployeeService { individual 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 e-mail:" + employee.getEmail()); } return employeeRepository.salvage(employee); } @Override public Listing<Employee> getAllEmployees () { return employeeRepository.findAll(); } @Override public Optional<Employee> getEmployeeById ( long id) { render employeeRepository.findById(id); } @Override public Employee updateEmployee (Employee updatedEmployee) { return employeeRepository.save(updatedEmployee); } @Override public void deleteEmployee ( long id) { employeeRepository.deleteById(id); } } 6. Unit Testing Service Layer using JUnit 5 and Mockito
Let united states of america beginning writing unit tests for EmployeeService. We should exist able to write unit tests for EmployeeService WITHOUT using any Spring features.
We are going to create a mock of EmployeeRepository using @Mock and create an EmployeeServiceImpl instance using the mock EmployeeRepository instance.
import net.javaguides.springboot.exception.ResourceNotFoundException; import net.javaguides.springboot.model.Employee; import net.javaguides.springboot.repository.EmployeeRepository; import net.javaguides.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.whatsoever; 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 coffee.util.List; import java.util.Optional; @ExtendWith(MockitoExtension.class) public class EmployeeServiceTests { @Mock private EmployeeRepository employeeRepository; @InjectMocks private EmployeeServiceImpl employeeService; individual 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 examination 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.salvage(employee)).willReturn(employee); Organisation.out.println(employeeRepository); System.out.println(employeeService); // when - activeness or the behaviour that we are going test Employee savedEmployee = employeeService.saveEmployee(employee); System.out.println(savedEmployee); // and then - verify the output assertThat(savedEmployee).isNotNull(); } // JUnit test for saveEmployee method @DisplayName("JUnit test for saveEmployee method which throws exception") @Exam public void givenExistingEmail_whenSaveEmployee_thenThrowsException(){ // given - precondition or setup given(employeeRepository.findByEmail(employee.getEmail())) .willReturn(Optional.of(employee)); System.out.println(employeeRepository); Organization.out.println(employeeService); // when - activity or the behaviour that we are going test org.junit.jupiter.api.Assertions.assertThrows(ResourceNotFoundException.grade, () -> { employeeService.saveEmployee(employee); }); // and so verify(employeeRepository, never()).save(any(Employee.class)); } // JUnit test for getAllEmployees method @DisplayName("JUnit exam 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 examination List<Employee> employeeList = employeeService.getAllEmployees(); // so - verify the output assertThat(employeeList).isNotNull(); assertThat(employeeList.size()).isEqualTo(2); } // JUnit exam for getAllEmployees method @DisplayName("JUnit test for getAllEmployees method (negative scenario)") @Test public void givenEmptyEmployeesList_whenGetAllEmployees_thenReturnEmptyEmployeesList(){ // given - precondition or setup Employee employee1 = Employee.builder() .id(2L) .firstName("Tony") .lastName("Stark") .e-mail("tony@gmail.com") .build(); given(employeeRepository.findAll()).willReturn(Collections.emptyList()); // when - activity or the behaviour that we are going examination List<Employee> employeeList = employeeService.getAllEmployees(); // then - verify the output assertThat(employeeList).isEmpty(); assertThat(employeeList.size()).isEqualTo(0); } // JUnit examination 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 examination 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 - activeness or the behaviour that we are going exam Employee updatedEmployee = employeeService.updateEmployee(employee); // and so - verify the output assertThat(updatedEmployee.getEmail()).isEqualTo("ram@gmail.com"); assertThat(updatedEmployee.getFirstName()).isEqualTo("Ram"); } // JUnit test for deleteEmployee method @DisplayName("JUnit examination for deleteEmployee method") @Test public void givenEmployeeId_whenDeleteEmployee_thenNothing(){ // given - precondition or setup long employeeId = 1L; willDoNothing().given(employeeRepository).deleteById(employeeId); // when - activity or the behaviour that we are going test employeeService.deleteEmployee(employeeId); // then - verify the output verify(employeeRepository, times(1)).deleteById(employeeId); } }
Notice that we are using the assertThat() method to assert the conditions using the AssertJ library.
Mockito @Mock annotation is useful when we want to use the mocked object at multiple places.
When nosotros want to inject a mocked object into some other mocked object, nosotros can use @InjectMocks notation. @InjectMock creates the mock object of the class and injects the mocks that are marked with the annotations @Mock into information technology.
JUnit test for saveEmployee method:
// JUnit test for saveEmployee method @DisplayName("JUnit examination for saveEmployee method") @Exam 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 - activeness 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 saveEmployee method which throws Exception:
// JUnit test for saveEmployee method @DisplayName("JUnit examination for saveEmployee method which throws exception") @Exam public void givenExistingEmail_whenSaveEmployee_thenThrowsException(){ // given - precondition or setup given(employeeRepository.findByEmail(employee.getEmail())) .willReturn(Optional.of(employee)); Organization.out.println(employeeRepository); System.out.println(employeeService); // when - action or the behaviour that we are going examination org.junit.jupiter.api.Assertions.assertThrows(ResourceNotFoundException.class, () -> { employeeService.saveEmployee(employee); }); // then verify(employeeRepository, never()).save(any(Employee.form)); } JUnit test for getAllEmployees method:
@DisplayName("JUnit test for getAllEmployees method") @Examination 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 - activeness or the behaviour that we are going examination List<Employee> employeeList = employeeService.getAllEmployees(); // and then - verify the output assertThat(employeeList).isNotNull(); assertThat(employeeList.size()).isEqualTo(2); } JUnit examination for getEmployeeById method
// 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(); // so assertThat(savedEmployee).isNotNull(); } JUnit examination for updateEmployee method:
// JUnit test for updateEmployee method @DisplayName("JUnit test for updateEmployee method") @Examination public void givenEmployeeObject_whenUpdateEmployee_thenReturnUpdatedEmployee(){ // given - precondition or setup given(employeeRepository.relieve(employee)).willReturn(employee); employee.setEmail("ram@gmail.com"); employee.setFirstName("Ram"); // when - action or the behaviour that nosotros are going test Employee updatedEmployee = employeeService.updateEmployee(employee); // and then - verify the output assertThat(updatedEmployee.getEmail()).isEqualTo("ram@gmail.com"); assertThat(updatedEmployee.getFirstName()).isEqualTo("Ram"); } JUnit test for deleteEmployee method
// JUnit test for deleteEmployee method @DisplayName("JUnit exam for deleteEmployee method") @Exam 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); } 7. Demo - Run JUnit Tests
Free Leap Boot Tutorial | Full In-depth Course | Learn Spring Boot in x Hours
Lookout this course on YouTube at Spring Kicking Tutorial | Fee 10 Hours Full Course
How To Unittest Spring Boot Service Layer,
Source: https://www.javaguides.net/2022/03/spring-boot-unit-testing-service-layer.html
Posted by: meadowshopper.blogspot.com

0 Response to "How To Unittest Spring Boot Service Layer"
Post a Comment