@DataJPATest with Spring Boot

Unit Test is so important in Software Development. Spring Boot provides @DataJpaTest annotation to make the writing test for JPA applications more simpler.

This tutorial shows you how to apply @DataJpaTest with TestEntityManager.

Related article:
How to use Spring JPA MySQL | Spring Boot
UnitTest – Maven skip test with SpringBoot
Spring Boot Unit Test for Spring MVC Controller

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.4.2.RELEASE

II. Overview
1. Data JPA tests

By default, @DataJpaTest will configure an in-memory embedded database, scan for @Entity classes and configure Spring Data JPA repositories. It is also transactional and rollback at the end of each test. If we wanna disable transaction management, we can use:

@Transactional(propagation = Propagation.NOT_SUPPORTED)

We can also inject a TestEntityManager bean specifically designed for tests which is an alternative to the JPA EntityManager.

@Autowired
private TestEntityManager entityManager;

Hence, our Test Class should be similar to:

@RunWith(SpringRunner.class)
@DataJpaTest
public class MyJPAUnitTest extends SpringJpaUnitTestApplicationTests {

	@Autowired
	private TestEntityManager entityManager;

	@Autowired
	CustomerRepository repository;
	
	@Test
	public void testExample() {...}
}
2. Project Structure


– Class Customer corresponds to entity and table customer, it should be implemented Serializable.
CustomerRepository is an interface extends CrudRepository, will be autowired in WebController for implementing repository methods and custom finder methods.
Dependencies for Spring Boot, JPA and in pom.xml, we also have dependency for hsqldb, this is used for JPA testing purpose.
MyJPAUnitTest is the main Test Class used for testing JPA and annotated with @DataJpaTest.

3. Step to do

– Create Spring Boot project & add Dependencies
– Create DataModel Class
– Create Spring JPA Repository Interface
– Create Class for Data JPA tests
– Run Spring Unit Test & Enjoy Result

III. Practice
1. Create Spring Boot project & add Dependencies

Open Spring Tool Suite, on Menu, choose File -> New -> Spring Starter Project, then fill each fields:

Open pom.xml and add Dependencies:

	
		
			org.springframework.boot
			spring-boot-starter
		

		
			org.springframework.boot
			spring-boot-starter-data-jpa
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			org.hsqldb
			hsqldb
			test
		
	
2. Create DataModel Class

Under package model, create class Customer.

Content of Customer.java:

package com.javasampleapproach.jpaunittest.entity;

import java.io.Serializable;

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 = "customer")
public class Customer implements Serializable {

	private static final long serialVersionUID = -3009157732242241606L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@Column(name = "firstname")
	private String firstName;

	@Column(name = "lastname")
	private String lastName;

	protected Customer() {
	}

	public Customer(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	public long getId() {
		return id;
	}

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

	@Override
	public String toString() {
		return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
	}
}

Annotation @Entity indicates that Customer is an Entity and @Table specifies the primary table (name customer) for the annotated @Entity.

@ID specifies the primary key and @GeneratedValue indicates generation strategy for value of primary key.

@Column: mapped column (in the table) for persistent fields (in Java class).

We have 2 constructor methods:
protected constructor will be used by Spring JPA.
public constructor is for creating instances.

3. Create Spring JPA Repository Interface

Under package model, create interface CustomerRepository.
This interface helps us do all CRUD functions for class Customer.

package com.javasampleapproach.jpaunittest.repo;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

import com.javasampleapproach.jpaunittest.entity.Customer;

public interface CustomerRepository extends CrudRepository {
	List findByLastName(String lastName);
}
4. Create Class for Data JPA tests

Under src/test/java, create a class named MyJPAUnitTest extending auto-generated testing class. We will test many cases with some methods inside this class.

package com.javasampleapproach.jpaunittest;

import static org.assertj.core.api.Assertions.assertThat;

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 com.javasampleapproach.jpaunittest.entity.Customer;
import com.javasampleapproach.jpaunittest.repo.CustomerRepository;

@RunWith(SpringRunner.class)
@DataJpaTest
public class MyJPAUnitTest {

	@Autowired
	private TestEntityManager entityManager;

	@Autowired
	CustomerRepository repository;

	@Test
	public void should_find_no_customers_if_repository_is_empty() {
		Iterable customers = repository.findAll();

		assertThat(customers).isEmpty();
	}

	@Test
	public void should_store_a_customer() {
		Customer customer = repository.save(new Customer("Jack", "Smith"));

		assertThat(customer).hasFieldOrPropertyWithValue("firstName", "Jack");
		assertThat(customer).hasFieldOrPropertyWithValue("lastName", "Smith");
	}

	@Test
	public void should_delete_all_customer() {
		entityManager.persist(new Customer("Jack", "Smith"));
		entityManager.persist(new Customer("Adam", "Johnson"));

		repository.deleteAll();

		assertThat(repository.findAll()).isEmpty();
	}

	@Test
	public void should_find_all_customers() {
		Customer customer1 = new Customer("Jack", "Smith");
		entityManager.persist(customer1);

		Customer customer2 = new Customer("Adam", "Johnson");
		entityManager.persist(customer2);

		Customer customer3 = new Customer("Peter", "Smith");
		entityManager.persist(customer3);

		Iterable customers = repository.findAll();

		assertThat(customers).hasSize(3).contains(customer1, customer2, customer3);
	}

	@Test
	public void should_find_customer_by_id() {
		Customer customer1 = new Customer("Jack", "Smith");
		entityManager.persist(customer1);

		Customer customer2 = new Customer("Adam", "Johnson");
		entityManager.persist(customer2);

		Customer foundCustomer = repository.findOne(customer2.getId());

		assertThat(foundCustomer).isEqualTo(customer2);
	}

}
5. Run Spring Unit Test & Enjoy Result

– Config maven build:
clean install
– Run project with mode JUnit Test
– Check results:

IV. Source Code

SpringJPAUnitTest



By grokonez | February 6, 2017.

Last updated on May 8, 2020.



Related Posts


2 thoughts on “@DataJPATest with Spring Boot”

  1. Thanks very nice example. however if i use @GeneratedValue(strategy = GenerationType.IDENTITY) in my model.
    It does not work and give error while creating tables.

  2. Thanks nice example. But it doesn’t work in spring boot version 2.1.4 and error message is “Consider defining a bean named ‘entityManagerFactory’ in your configuration.”

Got Something To Say:

Your email address will not be published. Required fields are marked *

*