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
- 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.
- 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.
- 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(){ }
- 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(){ }
- 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
You may also like-
No comments:
Post a Comment