Spring Boot 2 JPA Repository Testing using @DataJpaTest - RameshMF/spring-boot-developers-guide GitHub Wiki
In this article, we will learn how to test JPA Repository Testing using Spring boot provided @DataJpaTest annotation.
Sometimes we might want to test the persistence layer components of our application, which doesn’t require the loading of many components like controllers, security configuration, and so on. Spring Boot provides the @DataJpaTest annotation to test the Spring beans, which talk to relational databases.
As we know that 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.
Let's see how to test the Spring Data JPA repositories in a Spring Boot application. Let's develop a simple Spring boot maven project to demonstrate testing or Spring Data JPA repositories.
- Tools and Technologies Used
- Creating and Importing a Project
- Packaging Structure
- Add Spring Boot starter dependencies - pom.xml
- Create JPA Entity - Employee.java
- Create Spring JPA Repository - EmployeeRepository.java
- Testing Spring Data JPA Repositories Using @DataJpaTest
- Running Tests
- Spring Boot - 2.0.4.RELEASE
- JDK - 1.8 or later
- Spring Framework - 5.0.8 RELEASE
- Hibernate - 5.2.17.Final
- JPA
- H2
- Maven - 3.2+
- IDE - Eclipse or Spring Tool Suite (STS)
There are many ways to create a Spring Boot application. The simplest way is to use Spring Initializr at http://start.spring.io/, which is an online Spring Boot application generator.
Look at the above diagram, we have specified following details:
- Generate: Maven Project
- Java Version: 1.8 (Default)
- Spring Boot:2.0.4
- Group: net.guides.springboot2
- Artifact: springboot2-testing-examples
- Name: springboot2-testing-examples
- Package Name : net.guides.springboot2.springboottestingexamples
- Packaging: jar (This is the default value)
- Dependencies: Web, JPA, H2
Once, all the details are entered, click on Generate Project button will generate a spring boot project and downloads it. Next, Unzip the downloaded zip file and import it into your favorite IDE.
Following is the packing structure of our Employee Management Application -
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.guides.springboot2</groupId>
<artifactId>springboot-testing-examples</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-testing-examples</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</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>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</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>
</plugin>
</plugins>
</build>
</project>
package net.guides.springboot2.springboottestingexamples.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "employees")
public class Employee {
private long id;
private String firstName;
private String lastName;
private String emailId;
public Employee() {
}
public Employee(String firstName, String lastName, String emailId) {
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Column(name = "first_name", nullable = false)
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Column(name = "last_name", nullable = false)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Column(name = "email_address", nullable = false)
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", emailId=" + emailId
+ "]";
}
}
package net.guides.springboot2.springboottestingexamples.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.guides.springboot2.springboottestingexamples.model.Employee;
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>{
Employee findByFirstName(String username);
}
Let's test EmployeeRepository using the @DataJpaTest annotation.
package net.guides.springboot2.springboottestingexamples;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import net.guides.springboot2.springboottestingexamples.model.Employee;
import net.guides.springboot2.springboottestingexamples.repository.EmployeeRepository;
@RunWith(SpringRunner.class)
@DataJpaTest
public class EmployeeRepositoryTests {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testSaveEmployee() {
Employee employee = new Employee("admin", "admin", "[email protected]");
employeeRepository.save(employee);
Employee employee2 = employeeRepository.findByFirstName("admin");
assertNotNull(employee);
assertEquals(employee2.getFirstName(), employee.getFirstName());
assertEquals(employee2.getLastName(), employee.getLastName());
}
@Test
public void testGetEmployee() {
Employee employee = new Employee("admin", "admin", "[email protected]");
employeeRepository.save(employee);
Employee employee2 = employeeRepository.findByFirstName("admin");
assertNotNull(employee);
assertEquals(employee2.getFirstName(), employee.getFirstName());
assertEquals(employee2.getLastName(), employee.getLastName());
}
@Test
public void testDeleteEmployee() {
Employee employee = new Employee("admin", "admin", "[email protected]");
employeeRepository.save(employee);
employeeRepository.delete(employee);
}
}
By default, data JPA tests are transactional and roll back at the end of each test.If that is not what you want, you can disable transaction management for a test or for the whole class as follows:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ExampleNonTransactionalTests {
}
When you run EmployeeRepositoryTests, Spring Boot will autoconfigure the H2 in-memory embedded database (as you have the H2 database driver in the classpath) and run the tests.
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExampleRepositoryTests {
// ...
}
Data JPA tests may also inject a TestEntityManager bean, which provides an alternative to the standard JPA EntityManager that is specifically designed for tests. If you want to use TestEntityManager outside of @DataJpaTest instances, you can also use the @AutoConfigureTestEntityManager annotation. A JdbcTemplate is also available if you need that. The following example shows the @DataJpaTest annotation in use:
package net.guides.springboot2.springboottestingexamples;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;
import static org.assertj.core.api.Assertions.*;
@RunWith(SpringRunner.class)
@DataJpaTest
public class ExampleRepositoryTests {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository repository;
@Test
public void testExample() throws Exception {
this.entityManager.persist(new User("sboot", "1234"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getVin()).isEqualTo("1234");
}
}