Monday, September 22, 2025

Spring Boot Data JPA Repository Unit Test

In this article we'll see how to unit test JPA repositories and the persistence layer of an application in Spring Boot using the specialized annotation @DataJpaTest.

Required dependencies

First of all, ensure spring-boot-starter-test dependency is included. If you are using Maven then this dependency can be included in pom.xml like this.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

This starter bundles together common testing libraries like JUnit, Mockito, AssertJ, Spring Boot Test etc.

It is also suggested to use in-memory DB for unit testing the repository layer. This ensures that tests are self-contained and do not rely on an external database. @DataJpaTest annotation automatically configures an embedded database, if it is available on the classpath. So, it is also advisable to use H2 in-memory database, dependency for it is as given below.

<!-- H2 Database -->
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>test</scope>
</dependency>

Benefits of @DataJpaTest annotation

  1. Fast testing- @DataJpaTest annotation disables the full auto-configuration of Spring Boot application. It only configures the components requires for persistence layer testing like Entity classes, data JPA repositories. It also injects a TestEntityManager bean, which provides an alternative to the standard JPA EntityManager that is specifically designed for tests. Other components like Controllers, Service classes are not configured.
  2. Transactional by default- By default, data JPA tests are transactional and roll back at the end of each test which ensures a clean database state for subsequent tests. You can disable this default behavior by using @Transactional annotation. It can be used at the class level.
    @DataJpaTest
    @Transactional(propagation = Propagation.NOT_SUPPORTED) 
    public class UserRepositoryTest(){
    
    }
    

    It can also be used at method level.

  3. Default logging- Logging of executed SQL queries is done by default. This can be controlled using the showSql attribute of the @DataJpaTest annotation.
    @DataJpaTest(showSql = false)
    public class UserRepositoryTest(){
    
    }
    
  4. Providing properties- By using properties attribute you can specify additional Spring Boot configuration properties directly within the @DataJpaTest annotation.
    @DataJpaTest(properties = {
        "spring.datasource.url=jdbc:h2:mem:testdb",
        "spring.jpa.properties.hibernate.show_sql=true"
    })
    public class UserRepositoryTest(){
    }
    
  5. Using real database- @DataJpaTest annotation also provides flexibility to run tests against a real database. You can use the @AutoConfigureTestDatabase annotation for that purpose.
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = Replace.NONE)
    public class UserRepositoryTest(){
    }
    

Unit test for Spring Data JPA Repository using @DataJpaTest annotation

Please refer this post- Spring Boot + Data JPA + MySQL REST API CRUD Example to see the application for which we are going to write unit tests.

Entity class

The JPA entity class used for relational mapping is as given below.

User.java

import java.time.LocalDate;
import java.util.Objects;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;

@Entity
@Table(name="app_user")
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private int userId;
  
  @NotBlank(message = "First name is required")
  @Column(name="FIRST_NAME")
  private String firstName;
  
  @NotBlank(message = "Last name is required")
  @Column(name="LAST_NAME")
  private String lastName;
  @Column(name="USER_TYPE")
  private String userType;
  @Column(name="START_DATE")
  private LocalDate startDate;
    
  public int getUserId() {
    return userId;
  }
  public void setUserId(int userId) {
    this.userId = userId;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getUserType() {
    return userType;
  }
  public void setUserType(String userType) {
    this.userType = userType;
  }
  public LocalDate getStartDate() {
    return startDate;
  }
  public void setStartDate(LocalDate startDate) {
    this.startDate = startDate;
  }
 // toString(), hashCode() and equals() methods  
}

Please note that giving table name as "User" may cause problem with H2 DB as it is a reserved keyword in H2 database. That is why table name is "app_user".

Data JPA repository

JPA repository interface is as given below.

UserRepository.java

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.netjstech.model.User;

public interface UserRepository extends JpaRepository<User, Integer>{
  List<User> findUserByUserType(String userType);
}

Dialect changes in application.yaml file

If you are using in-memory database H2 for testing then you may add dialect for the same in the application.yaml or application.properties file.

jpa:
    properties:
      hibernate:
        sqldialect: org.hibernate.dialect.H2Dialect

With these changes in the Spring Boot application, you can write tests for the data JPA repository. Here is the full test class with 6 unit tests for save, update, delete, getAll, getById and findUserByUserType().

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import com.netjstech.dao.UserRepository;
import com.netjstech.model.User;

@DataJpaTest
class UserRepositoryTest {
  
  @Autowired
  UserRepository userRepositroy;
  
  @Test
  void testSaveUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
        
    assertThat(savedUser).isNotNull();
    assertNotNull(savedUser.getUserId());
    assertEquals(savedUser.getFirstName(), user.getFirstName());
    
  }
  
  @Test
  void testGetAllUsers() {
    User user1 = new User();
    user1.setFirstName("Ram");
    user1.setLastName("Tiwari");
    user1.setUserType("Platinum");
    user1.setStartDate(LocalDate.of(2025, 8, 26));
    
    User user2 = new User();
    user2.setFirstName("Shyam");
    user2.setLastName("Sharma");
    user2.setUserType("Gold");
    user2.setStartDate(LocalDate.of(2025, 7, 22));
    
    userRepositroy.save(user1);
    userRepositroy.save(user2);
    
    List<User> users = userRepositroy.findAll();
    
    assertNotNull(users);
    assertThat(users.size()).isEqualTo(2);
  }
  
  @Test
  void testGetUserById() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    User savedUser = userRepositroy.save(user);
    
    Optional<User> userFetched = userRepositroy.findById(savedUser.getUserId());
    
    assertThat(userFetched).isNotEmpty();
    
    assertEquals(user.getLastName(), userFetched.get().getLastName());
  }
  
  @Test
  void testGetAllUsersByType() {
    User user1 = new User();
    user1.setFirstName("Ram");
    user1.setLastName("Tiwari");
    user1.setUserType("Platinum");
    user1.setStartDate(LocalDate.of(2025, 8, 26));
    
    User user2 = new User();
    user2.setFirstName("Shyam");
    user2.setLastName("Sharma");
    user2.setUserType("Gold");
    user2.setStartDate(LocalDate.of(2025, 7, 22));
    
    User user3 = new User();
    user3.setFirstName("Anita");
    user3.setLastName("Verma");
    user3.setUserType("Gold");
    user3.setStartDate(LocalDate.of(2025, 7, 20));
    
    userRepositroy.save(user1);
    userRepositroy.save(user2);
    userRepositroy.save(user3);
    
    String userType = "Gold";
    
    List<User> user = userRepositroy.findUserByUserType(userType);
    
    assertNotNull(user);
    assertEquals(user.size(), 2);
  }
  
  @Test
  void testUpdateUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
    
    User userDB = userRepositroy.findById(savedUser.getUserId()).get();
    //update property
    userDB.setUserType("Gold");
    // save again
    savedUser = userRepositroy.save(userDB);
    
    assertNotNull(savedUser);
    assertEquals(savedUser.getUserType(), "Gold");
                
  }
  
  @Test
  void testDeletUser() {
    User user = new User();
    user.setFirstName("Ram");
    user.setLastName("Tiwari");
    user.setUserType("Platinum");
    user.setStartDate(LocalDate.of(2025, 8, 26));
    
    User savedUser = userRepositroy.save(user);
    
    userRepositroy.deleteById(savedUser.getUserId());
    
    Optional<User> userFetched = userRepositroy.findById(savedUser.getUserId());
    
    
    assertThat(userFetched).isEmpty();
  }
}

That's all for this topic Spring Boot Data JPA Repository Unit Test. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Boot Unit Test For REST API
  2. Spring Boot + Spring Security JWT Authentication Example
  3. Spring Boot Spring Initializr
  4. Spring Boot Microservice - Service Registration and Discovery With Eureka
  5. @Conditional Annotation in Spring

You may also like-

  1. Spring depends-on Attribute and @DependsOn With Examples
  2. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
  3. Spring Transaction Management Example - @Transactional Annotation and JDBC
  4. Spring Batch Processing With List of Objects in batchUpdate() Method
  5. Controlled and Uncontrolled Components in React
  6. Greatest Common Divisor (GCD) of Two Numbers Java Program
  7. Multi-Catch Statement in Java Exception Handling
  8. Strings in Python With Method Examples

No comments:

Post a Comment