0. 이 글의 목적
테스트 환경에서 H2를 사용하다 보니 jsonb같은 dialect를 이해하지 못하는 상황이 발생함
Postgresql95Dialect로 dialect에 대해 설정하는 등 다양한 방법을 시도해 보았으나 실패하다 테스트 DB자체를 바꾸면 되는 거 아닌가 하는 생각으로 구글링과 함께 스타트
1. 동작 방식 요약
postgresql 도커 컨테이너를 내부적으로 띄워서 h2가 아닌 이 컨테이너와 통신하며 테스트를 진행하는 방식입니다.
초기 이미지 pulling으로 인해 시간이 조금 더 걸릴 수 있습니다.
2. gradle 설정
testImplementation("org.testcontainers:testcontainers:1.17.3")
testImplementation("org.testcontainers:postgresql:1.17.3")
3. application properties 설정
//spring-jpa
jpa:
hibernate:
ddl-auto: create-drop
//spring-datasource
datasource:
schema: classpath:init.sql
driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
url: jdbc:tc:postgresql:///test-database
4. test code - 일부 코드는 비공개처리하였습니다.
@ActiveProfiles("test")
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ItemRepositoryTest {
companion object {
var postgres: PostgreSQLContainer<*> = PostgreSQLContainer(
"postgres:15-alpine"
).apply {
withDatabaseName("test-database")
}
@JvmStatic
@BeforeAll
fun beforeAll() {
postgres.start()
}
@JvmStatic
@AfterAll
fun afterAll() {
postgres.stop()
}
}
@Autowired
private lateinit var entityManager: EntityManager
private val itemRepository by lazy {
ItemRepository(
entityManager
)
}
@Test
fun `find_all_test`() {
val userId = 142L;
itemRepository.findAllItemByUserId(
)
}
}
5. 부분 설명 시작
5-1. 어노테이션
@ActiveProfiles("test")
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ItemRepositoryTest {
@DataJpaTest를 사용하는 경우 자동으로 embed된 datasource를 찾게 됩니다. 하지만 우리는 별도의 datasource를 사용하기 때문에 이에 대해 @AutoConfiguraeTesetDatabase를 오버라이딩해서 이를 막아줍니다.
5-2. PostgreSqlContainer 설정
companion object {
var postgres: PostgreSQLContainer<*> = PostgreSQLContainer(
"postgres:15-alpine"
).apply {
withDatabaseName("test-database")
}
@JvmStatic
@BeforeAll
fun beforeAll() {
postgres.start()
}
@JvmStatic
@AfterAll
fun afterAll() {
postgres.stop()
}
}
본디 static으로 실행해야 하는 탓에 companion object와 @JvmStatic의 조합으로 이를 가능하게 해 줍니다.
여기서 container는 alpine으로 진행했는데 다른 걸로 해도 별 문제는 없습니다.(아마도)
db의 이름을 test-database라 했는데 별도로 db의 이름이 명시적으로 필요한 경우 위에서의 properties와 함께 수정해서 사용하시면 됩니다.
postgres.start()와 postgres.stop()으로 테스트의 lifecycle에 맞춰 컨테이너에 대한 시작, 종료를 설정합니다.
5-3. 아마도..?
필요한 어노테이션과 각 테스트마다 container에 대한 컨트롤이 필요해서 모듈화 시킨 후 진행이 가능하지 않을까 하는 예상이 있습니다.
6. 그래서 TestContainer가 뭔데?
컨테이너를 띄워 테스트를 할 수 있게 해주는 좋은 도구입니다. 근데 이 컨테이너를 java로 띄워서 진행한다는 것이 가장 큰 메리트로 작용합니다. 우리는 별도의 docker설치 없이 dependency를 채워주는 것만으로도 이 편리함을 누릴 수 있습니다.
ref
'JAVA > spring' 카테고리의 다른 글
gRPC 붙이기, submodule을 곁들이고 github 멀티 계정의 귀찮음을 같이 처리하기 위한 스크립트 (0) | 2024.01.01 |
---|---|
Spring API Gateway 간단한 예제 (0) | 2023.12.10 |
Spring Cloud Netflix Zuul을 바라보며 (1) | 2023.10.28 |
Spring Security - CSRF를 disable?(간단, 요약) (0) | 2023.08.11 |
테스트 진행하기(Entity 기본과 약간의 Repository를 곁들인) (0) | 2023.08.05 |