Learn how to create and test a Spring Data JPA repository using JUnit and Mockito in this comprehensive guide. We’ll cover setting up the test environment, writing CRUD operations, and customizing queries.
By following this guide, you will ensure the robustness of the data layer in your Spring Boot application. Whether you are new to Spring Boot or an experienced developer, this guide will help you build a reliable and well-tested data layer.
Prerequisites Implementation of CRUD JUnit Tests for Spring Data JPAStep 1: Create Spring Boot ProjectWe can create the new Spring Boot project using Spring Initialize and creating the project add the following dependencies into the project.
- Spring Web
- Spring Data JPA
- MySQL Database Driver
- Lombok
- Spring DevTools
Once create the project then the file structure looks like the below image.
 Create the project Step 2: Application PropertiesOpen the application.properties and add the below code for the configuration of the MySQL Database and logs of the project.
spring.application.name=CRUD-JPA-Junit-Testing spring.datasource.url=jdbc:mysql://localhost:3306/blog_db spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect logging.level.org.springframework=DEBUG Step 3: Create the Employee EntityGo to src > main > java > org.example.crudjpajunittesting > entity > Employee and put the below code.
Java
package org.example.crudjpajunittesting.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
private double salary;
public Employee() {}
public Employee(String name, String department, double salary) {
this.name = name;
this.department = department;
this.salary = salary;
}
}
Step 4: Create the EmployeeRepository InterfaceGo to src > main > java > org.example.crudjpajunittesting > repository > EmployeeRepository and put the below code.
Java
package org.example.crudjpajunittesting.repository;
import org.example.crudjpajunittesting.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@Query("SELECT e FROM Employee e WHERE e.name = :name")
List<Employee> findByName(@Param("name") String name);
@Query(value = "SELECT * FROM Employee e WHERE e.department = ?1", nativeQuery = true)
List<Employee> findByDepartment(String department);
}
Step 5: Create the EmployeeService InterfaceGo to src > main > java > org.example.crudjpajunittesting > service > EmployeeService and put the below code.
Java
package org.example.crudjpajunittesting.service;
import java.util.List;
import java.util.Optional;
import org.example.crudjpajunittesting.entity.Employee;
import org.example.crudjpajunittesting.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public Employee saveEmployee(Employee employee) {
return employeeRepository.save(employee);
}
public Optional<Employee> getEmployeeById(Long id) {
return employeeRepository.findById(id);
}
public void deleteEmployee(Long id) {
employeeRepository.deleteById(id);
}
public List<Employee> getAllEmployees(Long id) {
return employeeRepository.findAll();
}
}
Step 6: Create the EmployeeController InterfaceGo to src > main > java > org.example.crudjpajunittesting > controller > EmployeeController and put the below code.
Java
package org.example.crudjpajunittesting.controller;
import java.util.List;
import org.example.crudjpajunittesting.entity.Employee;
import org.example.crudjpajunittesting.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@PostMapping
public Employee addEmployee(@RequestBody Employee employee) {
return employeeService.saveEmployee(employee);
}
@GetMapping("/{id}")
public Employee getEmployee(@PathVariable Long id) {
return employeeService.getEmployeeById(id).orElse(null);
}
// @GetMapping
// public List<Employee> getAllEmployees() {
// return employeeService.getAllEmployees();
// }
@PutMapping("/{id}")
public Employee updateEmployee(@PathVariable Long id, @RequestBody Employee employee) {
Employee existingEmployee = employeeService.getEmployeeById(id).orElse(null);
if (existingEmployee != null) {
existingEmployee.setName(employee.getName());
existingEmployee.setDepartment(employee.getDepartment());
existingEmployee.setSalary(employee.getSalary());
return employeeService.saveEmployee(existingEmployee);
}
return null;
}
@DeleteMapping("/{id}")
public void deleteEmployee(@PathVariable Long id) {
employeeService.deleteEmployee(id);
}
}
Step 7: Main classNo changes are required in the main class.
Java
package org.example.crudjpajunittesting;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CrudJpaJunitTestingApplication {
public static void main(String[] args) {
SpringApplication.run(CrudJpaJunitTestingApplication.class, args);
}
}
Testing packageStep 8: Create the EmployeerepositoryTest classGo to src > test > java > org.example.crudjpajunittesting > EmployeeRepositoryTest and put the below code.
Java
package org.example.crudjpajunittesting;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import org.example.crudjpajunittesting.entity.Employee;
import org.example.crudjpajunittesting.repository.EmployeeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class EmployeeRepositoryTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testSaveEmployee() {
Employee employee = new Employee("John Doe", "Engineering", 60000);
Employee savedEmployee = employeeRepository.save(employee);
assertNotNull(savedEmployee);
assertEquals("John Doe", savedEmployee.getName());
}
@Test
public void testGetEmployee() {
Employee employee = employeeRepository.save(new Employee("Jane Doe", "Marketing", 70000));
Employee fetchedEmployee = employeeRepository.findById(employee.getId()).orElse(null);
assertNotNull(fetchedEmployee);
assertEquals(employee.getId(), fetchedEmployee.getId());
}
@Test
public void testGetListOfEmployees() {
employeeRepository.save(new Employee("John Doe", "Engineering", 60000));
employeeRepository.save(new Employee("Jane Doe", "Marketing", 70000));
List<Employee> employees = employeeRepository.findAll();
assertNotNull(employees);
assertEquals(2, employees.size());
}
@Test
public void testUpdateEmployee() {
Employee employee = employeeRepository.save(new Employee("John Doe", "Engineering", 60000));
employee.setName("John Smith");
employeeRepository.save(employee);
Employee updatedEmployee = employeeRepository.findById(employee.getId()).orElse(null);
assertNotNull(updatedEmployee);
assertEquals("John Smith", updatedEmployee.getName());
}
@Test
public void testDeleteEmployee() {
Employee employee = employeeRepository.save(new Employee("John Doe", "Engineering", 60000));
employeeRepository.deleteById(employee.getId());
Employee deletedEmployee = employeeRepository.findById(employee.getId()).orElse(null);
assertNull(deletedEmployee);
}
}
Step 9: Create the EmployeeServiceTest classGo to src > test > java > org.example.crudjpajunittesting > EmployeeServiceTest and put the below code.
Java
package org.example.crudjpajunittesting;
import static org.mockito.Mockito.*;
import java.util.Optional;
import org.example.crudjpajunittesting.entity.Employee;
import org.example.crudjpajunittesting.repository.EmployeeRepository;
import org.example.crudjpajunittesting.service.EmployeeService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class EmployeeServiceTest {
@InjectMocks
private EmployeeService employeeService;
@Mock
private EmployeeRepository employeeRepository;
@BeforeEach
public void init() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testFindEmployeeById() {
Employee employee = new Employee("John Doe", "Engineering", 60000);
when(employeeRepository.findById(1L)).thenReturn(Optional.of(employee));
Employee found = employeeService.getEmployeeById(1L).orElse(null);
assertEquals("John Doe", found.getName());
}
}
Step 10: Create the EmployeeCotrollerTest classGo to src > test > java > org.example.crudjpajunittesting > EmployeeCotrollerTest and put the below code.
Java
package org.example.crudjpajunittesting;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.crudjpajunittesting.controller.EmployeeController;
import org.example.crudjpajunittesting.entity.Employee;
import org.example.crudjpajunittesting.service.EmployeeService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.mockito.Mockito.*;
@WebMvcTest(EmployeeController.class)
public class EmployeeControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private EmployeeService employeeService;
@Autowired
private ObjectMapper objectMapper;
@BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testGetEmployeeById() throws Exception {
Employee employee = new Employee("John Doe", "Engineering", 5000);
when(employeeService.getEmployeeById(1L)).thenReturn(Optional.of(employee));
mockMvc.perform(MockMvcRequestBuilders.get("/employees/1"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("John Doe"))
.andExpect(MockMvcResultMatchers.jsonPath("$.department").value("Engineering"))
.andExpect(MockMvcResultMatchers.jsonPath("$.salary").value(5000));
}
@Test
public void testGetAllEmployees() throws Exception {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee( "John Doe", "Engineering", 5000));
employees.add(new Employee( "Jane Doe", "HR", 4500));
when(employeeService.getAllEmployees()).thenReturn(employees);
mockMvc.perform(MockMvcRequestBuilders.get("/employees"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").value(1))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("John Doe"))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].department").value("Engineering"))
.andExpect(MockMvcResuśśltMatchers.jsonPath("$[0].salary").value(5000))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].id").value(2))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value("Jane Doe"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].department").value("HR"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].salary").value(4500));
}
// Add tests for other controller methods (add, update, delete) here
}
Step 11: Main Test classNo changes are required in this class
Java
package org.example.crudjpajunittesting;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@EntityScan(basePackages = "org.example.crudjpajunittesting.entity")
class CrudJpaJunitTestingApplicationTests {
@Test
void contextLoads() {
}
}
File: pom.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>CRUD-JPA-Junit-Testing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>CRUD-JPA-Junit-Testing</name>
<description>CRUD-JPA-Junit-Testing</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<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.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 12: Run the applicationWe can run the application then it will start at port 8080.
 Run the application CRUD JUnit Tests for Spring Data JPA Generate the Jar Filemvn clean package  Generate the Jar File for CRUD JUnit Tests for Spring Data JPA Run the test casesmvn clean test  Run the test cases CRUD JUnit Tests for Spring Data JPA Test Result Output CRUD JUnit Tests for Spring Data JPA Output This example that can demonstrates the essential aspect of the Spring Data JPA repository using the Junit and Mockito. By the following these steps, we can ensure that the data layer is robust and reliable of the application.
ConclusionIn this article, we can covered how to set up the Spring Boot project with JPA and Spring Data JPA to perform the CRUD operations of the Spring application. We can explored creating the JPA entity, repository and controller. We also delved into writing and running the JUnit tests for these components. By the following these steps, we can build and test the reliable CRUD applications using the Spring Boot, Spring Data JPA and JUnit.
Frequently Asked Questions on CRUD JUnit Tests for Spring Data JPAWhat is the difference between the unit testing and integration testing?Unit testing can be focuses on the individual components, while the integration testing can verifies the interactions between the multiple components of the application.
Why use the Mockito in testing?Mockito can allows for the creation of the mock objects to simulate the dependencies and it can enabling the isolated testing of the components under the testing.
How do i run the testcases?We can use your IDE’s built-in test runner or run the “mvn test” from the command line to execute and run the test cases of the application.
|