Demystifying Spring Boot Unit Test for Repository Layer: A Comprehensive Guide

Welcome to the realm of Spring Boot application development, where unit testing takes centre stage in ensuring the robustness and reliability of your repository layer. The repository layer plays a pivotal role in data access, serving as the bridge between your application and the underlying database. In our comprehensive guide, we embark on a journey to demystify the intricate world of “Spring Boot unit test for repository layer” This guide is designed to equip you with the essential knowledge and practical techniques required to master unit testing within the repository layer of your Spring Boot applications.

Unit testing in the context of the repository layer isn’t just about verifying data access functionality; it’s about constructing a robust testing strategy that guarantees data integrity, efficient query execution, and the overall health of your data layer. Throughout this article Demystifying Spring Boot Unit Test for Repository Layer: A Comprehensive Guide, we’ll explore the intricacies of unit testing with a focus on repository layer testing. We’ll delve into essential tools and libraries provided by Spring Boot, highlight best practices, and address common challenges. Real-world examples and hands-on exercises will empower you to confidently assess and enhance the reliability of your repository layer.

By the end of this journey, you’ll have a profound understanding of how to create effective unit tests for your Spring Boot repository layer. Your tests will not only ensure your application’s data access layer functions as expected but also help you catch potential issues early in the development process. So, if you’re ready to elevate your Spring Boot development skills and build data-driven applications with rock-solid repository layers, let’s embark on this enlightening exploration of “Spring Boot unit test for repository layer”.

This is the first part of the tutorial Demystifying Spring Boot Unit Test for Repository Layer: A Comprehensive Guide where we will learn about testing the repository layer. In the subsequent articles, we will learn about testing the other layers. So by the end, we will learn how to write integration test cases and end to end cases. So let’s get started –




Read More:

Complete Example for Spring Boot Unit Test for Repository Layer


We will create this example step by step, follow this tutorial till the end

Read: Writing JUnit test cases for Spring Boot Service layer

Watch the Video


Create spring boot project


There are many different ways to create a spring boot application, you can follow the below articles to create one –

>> Create spring boot application using Spring initializer
>> Create spring boot application in Spring tool suite [STS]
>> Create spring boot application in IntelliJ IDEA

Add maven dependencies


Open pom.xml and add the following dependencies –

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>in.bushansirgur</groupId>
	<artifactId>spring-boot-junit-crash-course</artifactId>
	<version>1.0.0</version>
	<name>spring-boot-junit-crash-course</name>
	<description>Spring boot Junit crash course</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</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>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>
  • We have added the spring-boot-starter-data-jpa dependency to perform the database operations.
  • We added an h2 dependency for storing the data in the database, it is a in-memory database.




  • We also added lombok which is java library, it reduces all the boilerplate code.
  • You can also notice the other dependency spring-boot-starter-test which is added by the spring initializer. 

Create entity class


Create Movie.java class in.bushansirgur.springbootjunit.model package and add the following content

package in.bushansirgur.springbootjunit.model;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "tbl_movies")
public class Movie {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	private String name;
	
	private String genera;
	
	private LocalDate releaseDate;
}

Create Repository


Create MovieRepository.java class in.bushansirgur.springbootjunit.repository package and add the following content

package in.bushansirgur.springbootjunit.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import in.bushansirgur.springbootjunit.model.Movie;

public interface MovieRepository extends JpaRepository<Movie, Long>{
	
	List<Movie> findByGenera(String genera);
}

So far we have created the Spring boot application and created the repository, now all we need to do is to write unit test cases for the MovieRepository.

Create JUnit Class


Create MovieRepositoryTest.java class inside src/test/java and add the following content

package in.bushansirgur.springbootjunit.repository;

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

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

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

import in.bushansirgur.springbootjunit.model.Movie;

@DataJpaTest
public class MovieRepositoryTest {
	
	@Autowired
	private MovieRepository movieRepository;
	
	@Test
	@DisplayName("It should save the movie to the database")
	void save() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		
		Movie newMovie = movieRepository.save(avatarMovie);
		assertNotNull(newMovie);
		assertThat(newMovie.getId()).isNotEqualTo(null);
	}
	
	@Test
	@DisplayName("It should return the movies list with size of 2")
	void getAllMovies() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		movieRepository.save(avatarMovie);
		
		Movie titanicMovie = new Movie();
		titanicMovie.setName("Titanic");
		titanicMovie.setGenera("Romance");
		titanicMovie.setReleaseDate(LocalDate.of(2004, Month.JANUARY, 10));
		movieRepository.save(titanicMovie);
		
		List<Movie> list = movieRepository.findAll();
		
		assertNotNull(list);
		assertThat(list).isNotNull();
		assertEquals(2, list.size());
	}
	
	@Test
	@DisplayName("It should return the movie by its id")
	void getMovieById() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		movieRepository.save(avatarMovie);
		
		Movie newMovie = movieRepository.findById(avatarMovie.getId()).get();
		
		assertNotNull(newMovie);
		assertEquals("Action", newMovie.getGenera());
		assertThat(newMovie.getReleaseDate()).isBefore(LocalDate.of(2000, Month.APRIL, 24));
	}
	
	@Test
	@DisplayName("It should return the movies list with genera ROMANCE")
	void getMoviesByGenera() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		movieRepository.save(avatarMovie);
		
		Movie titanicMovie = new Movie();
		titanicMovie.setName("Titanic");
		titanicMovie.setGenera("Romance");
		titanicMovie.setReleaseDate(LocalDate.of(2004, Month.JANUARY, 10));
		movieRepository.save(titanicMovie);
		
		List<Movie> list = movieRepository.findByGenera("Romance");
		
		assertNotNull(list);
		assertThat(list.size()).isEqualTo(1);
	}
	
	@Test
	@DisplayName("It should update the movie genera with FANTACY")
	void updateMovie() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		movieRepository.save(avatarMovie);
		
		Movie existingMovie = movieRepository.findById(avatarMovie.getId()).get();
		existingMovie.setGenera("Fantacy");
		Movie updatedMovie = movieRepository.save(existingMovie);
		
		assertEquals("Fantacy", updatedMovie.getGenera());
		assertEquals("Avatar", updatedMovie.getName());
	}
	
	@Test
	@DisplayName("It should delete the existing movie")
	void deleteMovie() {
		Movie avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 23));
		movieRepository.save(avatarMovie);
		Long id = avatarMovie.getId();
		
		Movie titanicMovie = new Movie();
		titanicMovie.setName("Titanic");
		titanicMovie.setGenera("Romance");
		titanicMovie.setReleaseDate(LocalDate.of(2004, Month.JANUARY, 10));
		movieRepository.save(titanicMovie);
		
		movieRepository.delete(avatarMovie);
		
		List<Movie> list = movieRepository.findAll();
		
		Optional<Movie> exitingMovie = movieRepository.findById(id);
		
		assertEquals(1, list.size());
		assertThat(exitingMovie).isEmpty();
		
	}
}

Now when you run the JUnit class, we should see the green bar indicating that all of the test cases are passed.

Screenshot-2022-08-23-at-1-17-37-AM

Now you see that we write the unit test cases for all the database operations like create, read, update and delete. Also, we write unit test cases for JPA query methods as well.




Every test case is divided into 3 parts

  • Arrange – Setting up the data required for the test case
  • Act – Calling the method or unit that is being tested
  • Assert – Verify whether the expected behavior is correct or not

You can also observe that we used @DataJpaTest annotation instead of @SpringBootTest. You can read more about @DataJpaTest annotation here

We have also used @DisplayName annotation, which is used to provide custom names to the unit test cases.

Now let’s refactor our code a little bit. We can use the JUnit life cycle method so that before running each test case, we can call a method init() so that we can set up the data that are required for all the test cases. @BeforeEach annotation will help us run the method before running every test case.

Let’s update the MovieRepositoryTest.java with following code

package in.bushansirgur.springbootjunit.repository;

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

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

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

import in.bushansirgur.springbootjunit.model.Movie;

@DataJpaTest
public class MovieRepositoryTest {
	
	@Autowired
	private MovieRepository movieRepository;

	private Movie avatarMovie;
	private Movie titanicMovie;
	
	@BeforeEach
	void init() {
		avatarMovie = new Movie();
		avatarMovie.setName("Avatar");
		avatarMovie.setGenera("Action");
		avatarMovie.setReleaseDate(LocalDate.of(2000, Month.APRIL, 22));
		
		titanicMovie = new Movie();
		titanicMovie.setName("Titanic");
		titanicMovie.setGenera("Romance");
		titanicMovie.setReleaseDate(LocalDate.of(1999, Month.MAY, 20));
	}
	
	@Test
	@DisplayName("It should save the movie to the database")
	void save() {
		//Arrange
		
		//Act
		Movie newMovie = movieRepository.save(avatarMovie);
		//Assert
		assertNotNull(newMovie);
		assertThat(newMovie.getId()).isNotEqualTo(null);
	}
	
	@Test
	@DisplayName("It should return the movies list with size of 2")
	void getAllMovies() {
		
		movieRepository.save(avatarMovie);
		movieRepository.save(titanicMovie);
		
		List<Movie> list = movieRepository.findAll();
		
		assertNotNull(list);
		assertThat(list).isNotNull();
		assertEquals(2, list.size());
	}
	
	@Test
	@DisplayName("It should return the movie by its id")
	void getMovieById() {
	
		movieRepository.save(avatarMovie);
		
		Movie existingMovie = movieRepository.findById(avatarMovie.getId()).get();
		
		assertNotNull(existingMovie);
		assertEquals("Action", existingMovie.getGenera());
		assertThat(avatarMovie.getReleaseDate()).isBefore(LocalDate.of(2000, Month.APRIL, 23));
	}
	
	@Test
	@DisplayName("It should update the movie with genera FANTACY")
	void updateMovie() {
		
		movieRepository.save(avatarMovie);
		Movie existingMovie = movieRepository.findById(avatarMovie.getId()).get();
		
		existingMovie.setGenera("Fantacy");
		Movie newMovie = movieRepository.save(existingMovie);
		
		assertEquals("Fantacy", newMovie.getGenera());
		assertEquals("Avatar", newMovie.getName());
	}
	
	@Test
	@DisplayName("It should delete the existing movie")
	void deleteMovie() {
		
		movieRepository.save(avatarMovie);
		Long id = avatarMovie.getId();
		
		movieRepository.save(titanicMovie);
		
		movieRepository.delete(avatarMovie);
		Optional<Movie> exitingMovie = movieRepository.findById(id);
		List<Movie> list = movieRepository.findAll();
		
		assertEquals(1, list.size());
		assertThat(exitingMovie).isEmpty();
		
	}
	
	@Test
	@DisplayName("It should return the movies list with genera ROMANCE")
	void getMoviesByGenera() {
		
		movieRepository.save(avatarMovie);
	
		movieRepository.save(titanicMovie);
		
		List<Movie> list = movieRepository.findByGenera("Romance");
		
		assertNotNull(list);
		assertThat(list.size()).isEqualTo(1);
	}
}

Now when we run the JUnit class, we should see all the test cases to pass.

Spring boot unit test for repository layer

Additional Resources

That’s it for this article, in the next article we will continue with the same application where we will write the JUnit test cases for other layers as well. Thank you so much for reading this post, if you feel this post helped you then consider sharing this with your friends, colleagues and social media.



Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

Leave a Reply