Spring Data JPA Repository Testing using Spring Boot @DataJpaTest

In this article, we will learn how to test Spring Data JPA Repositories 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.
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 develop a simple Spring boot maven project to demonstrate testing Spring Data JPA repositories.

Table of contents

  1. Tools and Technologies Used
  2. Creating and Importing a Project
  3. Packaging Structure
  4. Add Spring Boot starter dependencies - pom.xml
  5. Create JPA Entity - Employee.java
  6. Create Spring JPA Repository - EmployeeRepository.java
  7. Testing Spring Data JPA Repositories Using @DataJpaTest
  8. Running Tests

1. Tools and Technologies Used

  • 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)

2. Creating and Importing a Project

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.

3. Packaging Structure

Following is the packing structure for your reference -

4. The pom.xml File

<?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>

5. Create JPA Entity - Employee.java

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
       + "]";
    }
}

6. Create Spring JPA Repository - EmployeeRepository.java

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);
}

7. Testing Spring Data JPA Repositories Using @DataJpaTest

Let's test EmployeeRepository using the @DataJpaTest annotation.

EmployeeRepositoryTests.java

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", "admin@gmail.com");
        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", "admin@gmail.com");
        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", "admin@gmail.com");
        employeeRepository.save(employee);
        employeeRepository.delete(employee);
    }
}
If you want to run the tests against the actual registered database, you can annotate the test with @AutoConfigureTestDatabase(replace=Replace.NONE), which will use the registered DataSource instead of an in-memory datasource. 
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExampleRepositoryTests {
    // ...
}
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 {

}

8. Running Tests

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.
The output of the tests shown in below screenshot:

@DataJpaTest with TestEntityManager

The @DataJpaTest annotation also autoconfigures TestEntityManager, which is an alternative to the JPA EntityManager to be used in JPA tests.
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.boot.test.autoconfigure.orm.jpa.TestEntityManager;
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;

    @Autowired
    private TestEntityManager entityManager;
 
    @Test
    public void testSaveEmployee() {
  
        Employee employee = new Employee("admin", "admin", "admin@gmail.com");
        Integer id = entityManager.persistAndGetId(employee, Integer.class);
        assertNotNull(id);
        Employee employee2 = employeeRepository.findByFirstName("admin");
        assertNotNull(employee);
        assertEquals(employee2.getFirstName(), employee.getFirstName());
        assertEquals(employee2.getLastName(), employee.getLastName());
    } 
}


Comments