2 minute read

Usually we do not need to write tests for the functionalities provided by the framework, but we can do so when certain functionalities we use from the framework is not so clearcut. An example is when we are using the custom query creation by function method in Spring Data. Using back the example from my previous post - Getting started Spring Boot Application, we have the following query by function name - findAllByTopic_TopicId.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
    List<Post> findAllByTopic_TopicId(Long topicId);
}

If we are not that familiar with the function name conventions, it will be good to just write a test to ensure it works as intended.

To write a new test class for the repository, we need to use the @DataJpaTest annotation.

@ExtendWith(SpringExtension.class)
@DataJpaTest
public class PostRepositoryTest {

}

This annotation will help setup the environment you need to test the repository, like performing entity scan, so that you can use dependency injection, as well as turning on logging. With this annotation, the tests in the class will be transactional and rolled back at the end of each test, and it will use the embedded in-memory database. Do include h2 database in the dependencies of your gradle or maven file.

testImplementation 'com.h2database:h2:2.1.214'

Then we autowire a TestEntityManager and the repository we want to test into the class.

@Autowired
private TestEntityManager entityManager;

@Autowired
private PostRepositoryTest repository;

The TestEntityManager is a subset of EntityManager, with methods useful for tests. We’ll use it to insert data to our in memory database.

The context in our example is such that a Topic can have multiple Posts, joined by the foreign key TopicId. And our method is retrieving all the posts based on the TopicId.

We are using the GivenWhenThen style to write our test. Our precondition is to first create the data - a Topic and 2 Posts, then we persist and flush to save it the the database.

The action - denoted by the when, is where we execute the method that we want to test.

Lastly, the then section is where we specify the expected outcome with our assertion statements.

@Test
public void givenTopicHasPosts_whenFindAllByTopic_TopicId_thenReturnTopics(){
    //given
    Topic topic = new Topic("First Topic");
    entityManager.persist(topic);
    entityManager.flush();

    Post post1 = new Post("First Post", topic);
    Post post2 = new Post("Second Post", topic);
    entityManager.persist(post1);
    entityManager.persist(post2);
    entityManager.flush();

    //when
    List<Post> postList = postRepository.findAllByTopic_TopicId(topic.getTopicId());

    //then
    assertThat(postList.size(), is(2));
    assertThat(postList, containsInAnyOrder(post1, post2));
}

Lastly, we can add the following settings to the application.properties in the src/test/resources folder to show and format the sql that are generated by the framework in our log.

spring.jpa.show-sql = true
spring.jpa.properties.hibernate.format_sql=true

A working copy of the code is available on my github repository.

The source code for the above application is available on my github tagged as the initial-sample release, as the code will be updated subsequently as I introduced new articles on how to improve the solution.

This is part of a series illustrating how to build a backend Spring boot application.