3 In-Memory Database Usage Strategy for Spring Boot Integration Test

Abstract

Having integration test is always a good practice to have when you write your Spring Boot micro-services. Primary objective is to test each functionality of our code without using any mocking framework at integration test stage. There are few options available in open source community to use in-memory database instead of using a real one to facilitate this need.

In this article we are going to look at 3 easy-to-use in-memory database approach for our Spring Boot application testing.

We we will be using Postgres database for this illustration but the same concept can be extended to other supported databases as well.

Setup

Here is the simple project structure of a typical Spring Boot application for micro-service.

Simple Project Structure

The Spring Boot Application Class

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

The Controller Class

@RestController
@RequestMapping("/customer")
@Slf4j
public class CustomerController {

@Autowired
private CustomerService customerService;

@PostMapping
public Customer saveCustomer(@RequestBody Customer customer) {
log.info("Save customers {}", customer);
return customerService.saveCustomer(customer);
}
}

The Service Class

@Service
public class CustomerService {

@Autowired
private CustomerRepository customerRepository;

public Customer saveCustomer(Customer customer) {
return customerRepository.save(customer);
}
}

The Repository Class

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

The Entity Class

@Entity
@SequenceGenerator(name = "customer_generator", sequenceName = "customer_sequence", allocationSize = 1)
@Data
@Builder
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customer_generator")
@Column(name = "CUSTOMER_ID")
private Long customerId;

@Column(name = "CUSTOMER_NAME")
private String customerName;
}

Option 1 — h2 database

Good old h2 database is the simplest & easiest option among all. We just need to add the following dependency into the pom.xml

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

Let’s add the following to the application-test.properties

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Now this is our simple Test class

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
class DemoApplicationTests {

@Autowired
private MockMvc mockMvc;

@Test
void givenCustomer_whenPostCustomer_thenStatus200() throws Exception {
String request = "{\"customerName\": \"John\"}";
mockMvc.perform(post("/customer")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.customerId").value("1"));
}
}

Option 2 — Docker Container

This option uses powerful zonky spring-ready framework which internally involves testcontainers to run appropriate docker containers without writing any code.

You need to have Docker installed & running where this test is running.

Add the following dependency into the pom.xml

<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>

Add the following to the application-test.properties

zonky.test.database.postgres.docker.image=postgres:11-alpine

Add the annotation @AutoConfigureEmbeddedDatabase to the test class

@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@ActiveProfiles("test")
class DemoApplicationTests {

@Autowired
private MockMvc mockMvc;

@Test
void givenCustomer_whenPostCustomer_thenStatus200() throws Exception {
String request = "{\"customerName\": \"John\"}";
mockMvc.perform(post("/customer")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.customerId").value("1"));
}
}

Option 3— Embedded Database

This option also uses powerful zonky spring-ready framework which internally involves database-as-a-library and run the appropriate database in-memory.

Add the following dependencies into the pom.xml

<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-postgres</artifactId>
<version>1.3.0</version>
<scope>test</scope>
</dependency>

Add the following to the application-test.properties

zonky.test.database.provider=ZONKY

Add the annotation @AutoConfigureEmbeddedDatabase to the test class

@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureEmbeddedDatabase
@ActiveProfiles("test")
class DemoApplicationTests { @Autowired
private MockMvc mockMvc; @Test
void givenCustomer_whenPostCustomer_thenStatus200() throws Exception {
String request = "{\"customerName\": \"John\"}";
mockMvc.perform(post("/customer")
.contentType(MediaType.APPLICATION_JSON)
.content(request))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.customerId").value("1"));
}
}

Source Code

A working sample code is available here in GitHub repo.

Reference

https://github.com/zonkyio/embedded-database-spring-test

Credits: https://medium.com/@susantamon/3-in-memory-database-usage-strategy-for-spring-boot-integration-test-c107b8f1dcca

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments