Spring Application 통합 테스트 시 H2
같은 in-memory DB를 사용할 수 있지만
최대한 운영 환경과 유사한 상황에서 테스트하고자 한다면 Testcontainers를 통해 테스트 용 DB container를 띄우는 방식도 고려할 수 있을 것이다.
이번 포스팅은 MySQL Docker container를 사용하여 통합 테스트 시 인코딩 관련 이슈와 이를 해결하기 위해 인코딩 설정하는 방법에 대해 알아보겠다.
관련 코드는 여기에서 확인 가능하다.
인코딩 관련 이슈를 테스트를 재현하기 위해 MySQL
, JPA
dependency를 추가하고 SpringBoot Application을 생성한 뒤
Testcontainers JDBC MySQL depdencey를 추가한다.
그리고 다음과 같이 Entity
, Repository
를 세팅한다.
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id
@Entity
data class User(
@Id
val id: Long,
@Column
var name: String,
)
import org.springframework.data.jpa.repository.JpaRepository
interface UserRepository : JpaRepository<User, Long>
application.properties
는 아래와 같이 세팅한다.
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
세팅이 되었으면 이슈 재현을 위한 통합 테스트를 짜보자.
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.MySQLContainer
@SpringBootTest
class MysqlencodingApplicationTests {
companion object {
private val mysqlContainer = MySQLContainer<Nothing>("mysql:5.7").apply {
start()
}
@JvmStatic
@DynamicPropertySource
fun registerDbProperties(properties: DynamicPropertyRegistry) {
properties.add("spring.datasource.url", mysqlContainer::getJdbcUrl)
properties.add("spring.datasource.username", mysqlContainer::getUsername)
properties.add("spring.datasource.password", mysqlContainer::getPassword)
}
}
@Autowired
lateinit var userRepository: UserRepository
@Test
@DisplayName("한국어 저장 테스트")
fun koreanTest() {
userRepository.saveAll(
listOf(
User(1L, "Chris"),
User(2L, "손한국")
)
)
assertThat(userRepository.findById(1L).get().name).isEqualTo("Chris")
assertThat(userRepository.findById(2L).get().name).isEqualTo("손한국")
}
}
@Testcontainers
,@Container
어노테이션을 사용하지 않은 이유는 테스트 마다 중복해서 Container를 띄우는 것을 막기 위해 최초 application context 세팅 시 한 번만 Container를 띄우게 하기 위함이다.
관련해서는 언젠가 다른 포스팅에서... 참고
모든 세팅이 끝났다면 테스트를 실행시켜보자.
테스트 결과 영어와 같은 경우 정상적으로 값을 가져왔지만 한국어의 경우 위의 결과와 같이 ???
로 값을 가져온 것을 확인할 수 있다.
이는 MySQL DB 인코딩 설정으로 인해 발생한 오류로
직접 테스트 MySQL container에 접속하여 값을 조회하면 다음과 같이 영어는 잘 저장되나 한국어는 ???
로 저장된 것을 확인할 수 있다.
이 이슈를 해결하기 위해서는 MySQL DB 인코딩 설정이 필요한데
이는 단순하게 MySQL container 실행 후 Character Set을 지정하는 command를 실행 시켜주면 된다.
@SpringBootTest
class MysqlencodingApplicationTests {
companion object {
private val mysqlContainer = MySQLContainer<Nothing>("mysql:5.7").apply {
withCommand("mysqld", "--character-set-server=utf8mb4") // Character Set 설정
start()
}
@JvmStatic
@DynamicPropertySource
fun registerDbProperties(properties: DynamicPropertyRegistry) {
properties.add("spring.datasource.url", mysqlContainer::getJdbcUrl)
properties.add("spring.datasource.username", mysqlContainer::getUsername)
properties.add("spring.datasource.password", mysqlContainer::getPassword)
}
}
// ...
}
그리고 다시 테스트를 실행시키면 아래와 같이 정상적으로 테스트가 통과되는 것을 확인할 수 있다.
'Java & Kotlin > Spring' 카테고리의 다른 글
Spring Security 인증 기본 구조 (0) | 2021.07.18 |
---|---|
Spring Kafka 간단하게 맛보기 (0) | 2021.07.11 |
Spring JPA Querydsl 세팅 (with Kotlin) (0) | 2021.06.07 |
Rest Assured 테스트 시 redirect 막기 (0) | 2021.06.03 |
Github Actions로 PR 시 테스트를 돌려보자 (7) | 2021.04.21 |
댓글