티스토리 뷰

코프링으로 개발 시 마주친 에러 관련 포스팅입니다.

개발 환경은 다음과 같습니다.

  • Spring Boot Version : 3.0.1
  • Java Version : 17
  • Kotlin Version : 1.8.21
  • Kotest Version : 5.5.5

배경

kotest를 사용하는 프로젝트에서 통합 테스트를 위해 @Sql 어노테이션을 사용하여 데이터를 밀어넣어주었습니다.

통합 테스트 관련 내용은 아래 포스팅 참고해주세요.

 

[스프링+코틀린] mock 없이 통합 테스트하기

단위 테스트 책을 읽고 비즈니스 로직의 흐름을 담당하는 service layer(비즈니스 로직 흐름을 담당하는 layer) 테스트 코드를 시도했던 내용을 담는 포스팅입니다. 단위 테스트 - 예스24 소프트웨어

kkoon9.tistory.com

kotest 중 DescribeSpec을 사용했습니다.

허나, script가 동작되지 않았습니다.

디버깅을 해보니 kotest 내에선 @Sql 어노테이션 자체를 인식하지 못하는 것 같았습니다.

이렇게 추측했던 이유는 JUnit 기반의 똑같은 테스트 코드에서는 잘 동작했기 때문입니다.

확실하진 않지만 제가 원인으로는 다음과 같습니다.

kotest에서 @Sql이 동작하지 않은 이유 - listener

kotest에서는 기본적으로 listener가 동작하지 않는다고 합니다.

허나 @Sql은 SqlScriptsTestExecutionListener에 의해 실행된다고 나와있습니다.

그렇기 때문에 kotest 내부에서 listener를 직접 설정해주지 않으면 @Sql 어노테이션에 설정한 script 파일은 동작하지 않는거죠.

kotest에서 sql script 실행시키기

저는 그래서 @Sql 어노테이션이 아닌 다른 방법을 찾아보았습니다.

kotest에서는 JUnit의 @BeforeEach 같은 기능을 제공해주고 있습니다.

kotest에서는 그 기능을 hooks이라고 칭하고 있습니다.

 

Lifecycle hooks | Kotest

It is extremely common in tests to want to perform some action before and after a test, or before and after all tests in the same file.

kotest.io

저는 hooks에서 beforeSpec으로 sql script를 실행시켜주었습니다.

위 링크를 통해서 beforeSpec이 아닌 다른 기능이 필요하시면 참고 부탁드립니다.

package com.laboratorykkoon9.kotlinspring.cafe.service

import com.laboratorykkoon9.kotlinspring.cafe.repository.CafeRepository
import com.laboratorykkoon9.kotlinspring.cafe.service.model.CreateCafeDto
import com.laboratorykkoon9.kotlinspring.cafe.service.model.UpdateCafeDto
import com.laboratorykkoon9.kotlinspring.config.QuerydslConfig
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.DescribeSpec
import io.kotest.matchers.shouldBe
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.context.annotation.Import
import org.springframework.core.io.ClassPathResource
import org.springframework.data.domain.Pageable
import org.springframework.jdbc.datasource.init.ScriptUtils
import java.sql.SQLException
import javax.sql.DataSource

@DataJpaTest
@Import(QuerydslConfig::class)
@AutoConfigureTestDatabase(
    replace = AutoConfigureTestDatabase.Replace.NONE,
)
internal class CafeServiceTest(
    @Autowired private val cafeRepository: CafeRepository,
    @Autowired private val dataSource: DataSource,
): DescribeSpec({
    beforeSpec {
        try {
            dataSource.connection.use {conn ->
                ScriptUtils.executeSqlScript(
                    conn,
                    ClassPathResource("/sql/cafe.sql")
                )
            }
        } catch (e: SQLException) {
            throw RuntimeException(e)
        }
    }
    val cafeService = CafeService(cafeRepository)

    describe("createCafe") {
        context("이미 존재하는 카페 이름으로 생성을 시도하면") {
            val cafeDto = CreateCafeDto(
                name = "둥겸의 커피집"
            )

            it("예외를 던진다.") {
                shouldThrow<IllegalArgumentException> {
                    cafeService.createCafe(cafeDto)
                }
            }
        }
    }
})

beforeSpec 내부에 dataSource를 사용하여 sql문을 실행시켜주었습니다.

결론

단위 테스트 책을 읽고 통합 테스트는 mock이 아닌 실제 데이터로 테스트하기로 마음먹은 후로 계속해서 시행착오가 있었습니다.

드디어 kotest 내부에서도 통합 테스트를 하는 코드를 그럴싸하게 작성해본 것 같습니다.

추가로, 궁금하신 부분이나 잘못되었다고 생각하는 부분 코멘트 부탁드립니다.

읽어주셔서 감사합니다.

참고 링크

https://github.com/kotest/kotest/issues/1782

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함