Repository Testing :: TestContainer - up1/course-springboot-2024 GitHub Wiki

Repository testing with TestContainer

1. Add test container library in file pom.xml

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-testcontainers</artifactId>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.testcontainers</groupId>
	<artifactId>junit-jupiter</artifactId>
	<version>1.20.2</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.testcontainers</groupId>
	<artifactId>testcontainers</artifactId>
	<version>1.20.2</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.testcontainers</groupId>
	<artifactId>mysql</artifactId>
	<version>1.20.2</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>com.mysql</groupId>
	<artifactId>mysql-connector-j</artifactId>
	<version>8.3.0</version>
	<scope>runtime</scope>
</dependency>

2. Config application.properties

File src/main/resources/application.properties

spring.sql.init.mode=always


spring.jpa.hibernate.ddl-auto=none
spring.datasource.hikari.maxLifetime=600000
spring.datasource.initialization-mode=always
# In MySQL 8, serverTimezone=UTC is deprecated in favor of connectionTimeZone
spring.datasource.url=jdbc:mysql://localhost:3306/test?connectionTimeZone=UTC
# The Hibernate dialect doesn't need to be explicitly specified anymore in Hibernate 6
# spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.datasource.username=root
spring.datasource.password=secret

File src/tests/resources/application.properties

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.sql.init.mode=never

3. Create tables in database src/main/resources/schema.sql

CREATE TABLE IF NOT EXISTS my_user (
    id int(10) PRIMARY KEY,
    first_name VARCHAR(256) NOT NULL,
    last_name VARCHAR(256) NOT NULL,
    age int(10),
    CONSTRAINT uc_user_first_last_name UNIQUE(first_name, last_name),
    INDEX idx_user_id (id)
) engine=InnoDB;

4. Working with TestContainer in Spring Boot 3

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class UserRepositoryMySQLTest {

    @Container
    @ServiceConnection
    static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql");

    @DynamicPropertySource
    static void mysqlProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", () -> mySQLContainer.getJdbcUrl());
        registry.add("spring.datasource.driverClassName", () -> mySQLContainer.getDriverClassName());
        registry.add("spring.datasource.username", () -> mySQLContainer.getUsername());
        registry.add("spring.datasource.password", () -> mySQLContainer.getPassword());
        registry.add("spring.sql.init.mode", () -> "always");
    }

    @Autowired
    private UserRepository userRepository;

    @Test
    public void case01() {
        // Arrange
        MyUser dummy = new MyUser();
        dummy.setId(1L);
        dummy.setFirstName("Somkiat");
        dummy.setLastName("Pui");
        userRepository.saveAndFlush(dummy);
        // Act
        Optional<MyUser> result = userRepository.findById(1L);
        // Assert
        assertEquals(1, result.get().getId());
        assertEquals("Somkiat", result.get().getFirstName());
    }

}

5. Working with Docker compose

pom.xml

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-docker-compose</artifactId>
	<optional>true</optional>
</dependency>

Create file docker-compose.yml

services:
  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: test
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
⚠️ **GitHub.com Fallback** ⚠️