Horje
CRUD JUnit Tests for Spring Data JPA

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 JPA

Step 1: Create Spring Boot Project

We 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

Create the project

Step 2: Application Properties

Open 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 Entity

Go 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 Interface

Go 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 Interface

Go 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 Interface

Go 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 class

No 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 package

Step 8: Create the EmployeerepositoryTest class

Go 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 class

Go 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 class

Go 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 class

No 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 application

We can run the application then it will start at port 8080.

testlog-compressed

Run the application CRUD JUnit Tests for Spring Data JPA

Generate the Jar File

mvn clean package
Generate the Jar File

Generate the Jar File for CRUD JUnit Tests for Spring Data JPA

Run the test cases

mvn clean test
Run the test cases of CRUD JUnit Tests for Spring Data JPA

Run the test cases CRUD JUnit Tests for Spring Data JPA

Test Result Output

testresult output of CRUD JUnit Tests for Spring Data JPA

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.

Conclusion

In 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 JPA

What 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.




Reffered: https://www.geeksforgeeks.org


Automation Testing

Related
What are Exclude and Include Test Methods in TestNG? What are Exclude and Include Test Methods in TestNG?
TestNG Annotations in Selenium Webdriver with Examples TestNG Annotations in Selenium Webdriver with Examples
Benefits of Automation Testing Benefits of Automation Testing
Top Test Automation mistakes and Tips for QA teams to avoid them Top Test Automation mistakes and Tips for QA teams to avoid them
What to Look for Before Hiring QA Engineers? What to Look for Before Hiring QA Engineers?

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
13