In this tutorial, we will learn how to test repository or DAO layer using Spring boot provided @DataJpaTest annotation.
We will write a JUnit 5 test case for CRUD operations - Create, Read, Update and Delete.
The @DataJpaTest annotation doesn’t load other Spring beans (@Component, @Controller, @Service, and annotated beans) into ApplicationContext.
The annotations used are:
We will write a JUnit 5 test case for CRUD operations - Create, Read, Update and Delete.
YouTube Video
@DataJpaTest Annotation Overview
The Spring boot provides @DataJpaTest annotation. This annotation will disable full auto-configuration and instead apply only configuration relevant to JPA tests. By default, it will use an embedded, in-memory H2 database instead of the one declared in the configuration file, for faster test running time as compared to disk file database.We will create Spring Boot project from scratch using Spring data JPA ( Hibernate) and H2 database.
1. Create Spring Boot Project
Spring Boot provides a web tool called https://start.spring.io to bootstrap an application quickly. Just go to https://start.spring.io and generate a new spring boot project.
Use the below details in the Spring boot creation:
Project Name: spring-data-data-testing
Project Type: Maven
Choose dependencies: Spring Data JPA, H2 database, Lombok, Spring Boot Dev Tools
Package name: net.javaguides.springboot
2. Maven Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</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>
3. Create JPA Entity
Let's create an entity package inside a base package "net.javaguides.springboot". Within the entity package, create a Employee class with the following content:
package net.javaguides.springboot;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.persistence.*;
@Data
@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(name = "email", nullable = false)
private String email;
}
@Data: This annotation is from the Lombok library and is used to automatically generate getters and setters for all fields in the class, as well as implementations of toString(), equals(), and hashCode(). This reduces the amount of boilerplate code that needs to be written.
@AllArgsConstructor: This annotation is also from Lombok and generates a constructor that takes all of the fields in the class as arguments.
@NoArgsConstructor: This annotation is also from Lombok and generates a no-argument constructor.
@Builder: This annotation is also from Lombok and generates a builder pattern for the class, which provides a convenient way to create instances of the class with default or optional values for some fields.
@Entity: This annotation is from the Java Persistence API (JPA) and marks the class as an entity that can be persisted to a database.
@Table(name = "employees"): This annotation specifies the name of the table that corresponds to this entity in the database.
We need to specify the execution order because JUnit doesn’t run test methods in the order they appear in the code. So we need to use the @TestMethodOrder and @Order annotations to execute test cases in ascending order.
Note that we have used @Rollback(false) to disable roll back to the data will be committed to the database and available for the next test methods which will run separately.
← Back to All Spring Data JPA Tutorials
4. Create Spring Data JPA Repository
The next thing we’re gonna do is create a repository to access a User’s data from the database.
The JpaRepository interface defines methods for all the CRUD operations on the entity, and a default implementation of the JpaRepository called SimpleJpaRepository.
Let's create a repository package inside a base package "net.javaguides.springdatarest". Within the repository package, create a EmployeeRepository interface with the following content:
package net.javaguides.springboot;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
Optional<Employee> findByEmail(String email);
}
5. CRUD JUnit Tests for Spring Data JPA Repository
Spring Boot provides the @DataJpaTest annotation to test the persistence layer components that will autoconfigure in-memory embedded databases and scan for @Entity classes and Spring Data JPA repositories. The @DataJpaTest annotation doesn’t load other Spring beans (@Components, @Controller, @Service, and annotated beans) into ApplicationContext.
We need to specify the execution order because JUnit doesn’t run test methods in the order they appear in the code. So we need to use the @TestMethodOrder and @Order annotations to execute test cases in ascending order.
Head over to test package. Let's create a repository package inside a base package "test.net.javaguides.springboot". Within the repository package, create a EmployeeRepositoryTest class with the following content:
package net.javaguides.springboot;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.Rollback;
import javax.sql.DataSource;
import java.util.List;
import java.util.Optional;
@DataJpaTest
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class EmployeeRepositoryTests {
@Autowired
private EmployeeRepository employeeRepository;
// JUnit test for saveEmployee
@Test
@Order(1)
@Rollback(value = false)
public void saveEmployeeTest(){
Employee employee = Employee.builder()
.firstName("Ramesh")
.lastName("Fadatare")
.email("ramesh@gmail.com")
.build();
employeeRepository.save(employee);
Assertions.assertThat(employee.getId()).isGreaterThan(0);
}
@Test
@Order(2)
public void getEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
Assertions.assertThat(employee.getId()).isEqualTo(1L);
}
@Test
@Order(3)
public void getListOfEmployeesTest(){
List<Employee> employees = employeeRepository.findAll();
Assertions.assertThat(employees.size()).isGreaterThan(0);
}
@Test
@Order(4)
@Rollback(value = false)
public void updateEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
employee.setEmail("ram@gmail.com");
Employee employeeUpdated = employeeRepository.save(employee);
Assertions.assertThat(employeeUpdated.getEmail()).isEqualTo("ram@gmail.com");
}
@Test
@Order(5)
@Rollback(value = false)
public void deleteEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
employeeRepository.delete(employee);
//employeeRepository.deleteById(1L);
Employee employee1 = null;
Optional<Employee> optionalEmployee = employeeRepository.findByEmail("ram@gmail.com");
if(optionalEmployee.isPresent()){
employee1 = optionalEmployee.get();
}
Assertions.assertThat(employee1).isNull();
}
}
Let's understand above JUnit test cases one by one.
JUnit test for saveEmployee:
// JUnit test for saveEmployee
@Test
@Order(1)
@Rollback(value = false)
public void saveEmployeeTest(){
Employee employee = Employee.builder()
.firstName("Ramesh")
.lastName("Fadatare")
.email("ramesh@gmail.com")
.build();
employeeRepository.save(employee);
Assertions.assertThat(employee.getId()).isGreaterThan(0);
}
We have also used assertThat() method from AssertJ library for more readability than using JUnit’s assertion methods.
JUnit test for getEmployee:
We write a test to retrieve employee by it's Id and test the same with id 1:
@Test
@Order(2)
public void getEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
Assertions.assertThat(employee.getId()).isEqualTo(1L);
}
We have also used assertThat() method from AssertJ library for more readability than using JUnit’s assertion methods.
JUnit test for getListOfEmployees:
We write a test method to retrieve list of employees from database and test it's size:
@Test
@Order(3)
public void getListOfEmployeesTest(){
List<Employee> employees = employeeRepository.findAll();
Assertions.assertThat(employees.size()).isGreaterThan(0);
}
We have also used assertThat() method from AssertJ library for more readability than using JUnit’s assertion methods.
JUnit test for updateEmployee:
We write a JUnit test method to test update employee operation:
@Test
@Order(4)
@Rollback(value = false)
public void updateEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
employee.setEmail("ram@gmail.com");
Employee employeeUpdated = employeeRepository.save(employee);
Assertions.assertThat(employeeUpdated.getEmail()).isEqualTo("ram@gmail.com");
}
Note that we have used @Rollback(false) to disable roll back to the data will be committed to the database and available for the next test methods which will run separately.
We have also used assertThat() method from AssertJ library for more readability than using JUnit’s assertion methods.
JUnit test for deleteEmployee:
We write a JUnit test method to test delete employee operation:
@Test
@Order(5)
@Rollback(value = false)
public void deleteEmployeeTest(){
Employee employee = employeeRepository.findById(1L).get();
employeeRepository.delete(employee);
//employeeRepository.deleteById(1L);
Employee employee1 = null;
Optional<Employee> optionalEmployee = employeeRepository.findByEmail("ram@gmail.com");
if(optionalEmployee.isPresent()){
employee1 = optionalEmployee.get();
}
Assertions.assertThat(employee1).isNull();
}
Here the output of the CRUD JUnit tests:
sir, please write test cases for controller layer for crud operations. please.
ReplyDelete