Unit Tests for Spring Data JDBC Repositories

A Unit Testing Guide for Spring Data JDBC Repositories and Entities. Covers examples of using TestNG or JUnit to unit test Spring Data JDBC.

Overview

Unit Tests are an important aspect of Software Component Development. They ensure that various individual components or units of an application behave as per the specification.

In this tutorial we will cover, how to write Unit Tests for Spring Data JDBC entities and Repositories. We will write tests using TestNG and then with JUnit.

Repository & Entity Bean

Before we begin writing our Unit Tests, let’s have a look at the entity bean and the repository that we will test.

Entity Bean

The entity has a few basic fields and an @Id Field. We are using Lombok to generate an All Argument Constructor and standard getter and setter methods. However, these are not required in order to persist it as an entity.

package com.amitph.spring.tutorials.springdatajdbc.repo; import lombok.AllArgsConstructor; import lombok.Data; import org.springframework.data.annotation.Id; @Data @AllArgsConstructor public class Student { @Id private Long studentId; private String firstName; private String lastName; private Integer year; }
Code language: Java (java)

Repository

The repository interface is extending from CrudRepository, that provides basic DB operations via predefined query methods. We have added two custom query methods to the interface.

package com.amitph.spring.tutorials.springdatajdbc.repo; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface StudentRepository extends CrudRepository<Student, Long> { List<Student> findByLastName(@Param("lName") String lastName); List<Student> findByLastNameIgnoreCase(@Param("lName") String lastName); }
Code language: Java (java)

Our demo application is a Spring Boot application that you can refer from Introduction to Spring Data JDBC Tutorial.

Unit Tests Setup

For the unit test purpose, we will use H2 Database, which is an in-memory database. When we add h2 dependency in a Spring Boot Project, it automatically configures the database for us.

H2 Database dependency

Make sure, you add the latest version of the database.

<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>{version}</version> <scope>test</scope> </dependency>
Code language: HTML, XML (xml)

We also need to setup database table into the H2 database. To do that, we can use liquibase or data.sql.

In this example, we are using a liquibase script to populate the table on application startup. This is our application-test.properties file configures the liquibase changelog file path.

application-test.yml

spring: liquibase: change-log: classpath:db/liquibase-changelog.xml
Code language: YAML (yaml)

Note that, we are using separate Spring Profile for tests. Because of this our applications main application.yml file can use a different database, while the unit tests can run on H2 Database.

Spring Data JDBC TestNG Tests

In order to use TestNG we need to add its dependency into our project.

<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>{version}</version> <scope>test</scope> </dependency>
Code language: HTML, XML (xml)

Next, we will create a Test class that extends AbstractTransactionalTsetNGContextTests class. Also, we use @DataJdbcTest annotation which is responsible for taking care of initialising JdbcTemplate and repository, which internally uses JdbcTemplate.

Also note that we are using test as our active profile.

@DataJdbcTest @ActiveProfiles("test") public class StudentRepositoryTest extends AbstractTransactionalTestNGSpringContextTests { @Autowired StudentRepository repository; @Test public void testFindByLastName() { List<Student> expectedList = entities() .map(repository::save) .filter(student -> student.getLastName().equals("Stark")) .collect(Collectors.toList()); List<Student> actualList = repository.findByLastName("Stark"); Assert.assertEquals(actualList, expectedList); } @Test public void testFindByLastNameIgnoreCase() { List<Student> expectedList = entities() .map(repository::save) .filter(student -> student.getLastName().equalsIgnoreCase("Stark")) .collect(Collectors.toList()); List<Student> actualList = repository.findByLastNameIgnoreCase("Stark"); Assert.assertEquals(actualList, expectedList); } private Stream<Student> entities() { return Stream.of( new Student(null, "Arya", "Stark", 2023), new Student(null, "Jon", "Snow", 2023), new Student(null, "Rob", "Stark", 2023), new Student(null, "Ned", "stark", 2023) ); } }
Code language: Java (java)

First, we are creating a stream of dummy entities and inserting them into the in-memory database using repository.save() method. Then for each of the returned entities, we apply the same filter which is expected from the actual method. We then collect the stream results into a list of expected elements. Finally, if the expected and actual list matches, our tests pass.

Note: For this example we are using repository to insert the dummy records. Alternatively, you can use JdbcTemplate to do that. You will have to autowire @JdbcTemplate into the test.

@Autowired JdbcTemplate testJdbcTemplate;
Code language: Java (java)

Spring Data JDBC JUnit Tests

In order to run JUnit tests, we can follow the same setup. We will add JUnit dependency.

<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>{version}</version> <scope>test</scope> </dependency>
Code language: HTML, XML (xml)

In order to launch the spring context, we need to specify @RunWith annotation.

@RunWith(SpringRunner.class)
Code language: Java (java)

Next, is the example of JUnit Tests for the Student Repository.

@RunWith(SpringRunner.class) @DataJdbcTest @ActiveProfiles("test") public class StudentRepositoryTest { @Autowired StudentRepository repository; @Test public void testFindByLastName() { List<Student> expectedList = entities() .map(repository::save) .filter(student -> student.getLastName().equals("Stark")) .collect(Collectors.toList()); List<Student> actualList = repository.findByLastName("Stark"); Assert.assertEquals(expectedList, actualList); } @Test public void testFindByLastNameIgnoreCase() { List<Student> expectedList = entities() .map(repository::save) .filter(student -> student.getLastName().equalsIgnoreCase("Stark")) .collect(Collectors.toList()); List<Student> actualList = repository.findByLastNameIgnoreCase("Stark"); Assert.assertEquals(expectedList, actualList); } private Stream<Student> entities() { return Stream.of( new Student(null, "Arya", "Stark", 2023), new Student(null, "Jon", "Snow", 2023), new Student(null, "Rob", "Stark", 2023), new Student(null, "Ned", "stark", 2023) ); } }
Code language: Java (java)

Summary

In this detailed tutorial we learned How to Write Unit tests for Spring Data JDBC Repository. We covered a basic setup that is required for writing Unit Tests. Then we wrote our unit tests using TestNG and with JUnit.

Visit Spring Tutorials to learn more about Spring and Spring Boot.

For the full source code visit our Github Repository.