generated from pricelees/issue-pr-template
<!-- 제목 양식 --> <!-- [이슈번호] 작업 요약 (예시: [#10] Gitea 템플릿 생성) --> ## 📝 관련 이슈 및 PR **PR과 관련된 이슈 번호** - #13 ## ✨ 작업 내용 <!-- 어떤 작업을 했는지 알려주세요! --> theme 패키지 내 코드 및 테스트 코틀린 전환 ## 🧪 테스트 <!-- 어떤 테스트를 생각했고 진행했는지 알려주세요! --> 다른 테스트는 코틀린으로 전환 시 크게 문제가 없었으나, GET /themes/most-reserved-last-week API의 경우 쿼리에 크게 의존하여 mocking을 사용하는 기존 테스트로 처리하기 애매한 부분이 있었음. 따라서, API 테스트는 mocking이 아닌 RestAssured를 이용한 실제 테스트로 진행하였고 \@RequestParam, 날짜 등 실제 비즈니스와 관련된 부분을 위주로 처리하고 쿼리 자체는 Repository 테스트에서 상세하게 검증하였음. ## 📚 참고 자료 및 기타 <!-- 참고한 자료, 또는 논의할 사항이 있다면 알려주세요! --> 패키지를 reservation 안에 넣는 것은 고민이 조금 더 필요할 것 같음. 현재는 단일 매장에 대한 서비스지만 매장별로 분리하는 것을 고민중인 만큼 코틀린 마이그레이션이 끝난 이후 생각해볼 예정 Reviewed-on: #15 Co-authored-by: pricelees <priceelees@gmail.com> Co-committed-by: pricelees <priceelees@gmail.com>
104 lines
3.3 KiB
Kotlin
104 lines
3.3 KiB
Kotlin
package roomescape.theme.business
|
|
|
|
import io.kotest.assertions.assertSoftly
|
|
import io.kotest.assertions.throwables.shouldThrow
|
|
import io.kotest.core.spec.style.FunSpec
|
|
import io.kotest.matchers.shouldBe
|
|
import io.mockk.every
|
|
import io.mockk.mockk
|
|
import org.springframework.data.repository.findByIdOrNull
|
|
import org.springframework.http.HttpStatus
|
|
import roomescape.common.exception.ErrorType
|
|
import roomescape.common.exception.RoomescapeException
|
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
|
import roomescape.theme.infrastructure.persistence.ThemeRepository
|
|
import roomescape.theme.web.ThemeRequest
|
|
import roomescape.util.ThemeFixture
|
|
|
|
class ThemeServiceTest : FunSpec({
|
|
|
|
val themeRepository: ThemeRepository = mockk()
|
|
val themeService = ThemeService(themeRepository)
|
|
|
|
context("findThemeById") {
|
|
val themeId = 1L
|
|
test("조회 성공") {
|
|
val theme: ThemeEntity = ThemeFixture.create(id = themeId)
|
|
every {
|
|
themeRepository.findByIdOrNull(themeId)
|
|
} returns theme
|
|
|
|
theme.id shouldBe themeId
|
|
}
|
|
|
|
test("ID로 테마를 찾을 수 없으면 400 예외를 던진다.") {
|
|
every {
|
|
themeRepository.findByIdOrNull(themeId)
|
|
} returns null
|
|
|
|
val exception = shouldThrow<RoomescapeException> {
|
|
themeService.findThemeById(themeId)
|
|
}
|
|
|
|
exception.errorType shouldBe ErrorType.THEME_NOT_FOUND
|
|
}
|
|
}
|
|
|
|
context("findAllThemes") {
|
|
test("모든 테마를 조회한다.") {
|
|
val themes = listOf(ThemeFixture.create(id = 1, name = "t1"), ThemeFixture.create(id = 2, name = "t2"))
|
|
every {
|
|
themeRepository.findAll()
|
|
} returns themes
|
|
|
|
assertSoftly(themeService.findAllThemes()) {
|
|
this.themes.size shouldBe themes.size
|
|
this.themes[0].name shouldBe "t1"
|
|
this.themes[1].name shouldBe "t2"
|
|
}
|
|
}
|
|
}
|
|
|
|
context("save") {
|
|
test("테마 이름이 중복되면 409 예외를 던진다.") {
|
|
val name = "Duplicate Theme"
|
|
|
|
every {
|
|
themeRepository.existsByName(name)
|
|
} returns true
|
|
|
|
val exception = shouldThrow<RoomescapeException> {
|
|
themeService.save(ThemeRequest(
|
|
name = name,
|
|
description = "Description",
|
|
thumbnail = "http://example.com/thumbnail.jpg"
|
|
))
|
|
}
|
|
|
|
assertSoftly(exception) {
|
|
this.errorType shouldBe ErrorType.THEME_DUPLICATED
|
|
this.httpStatus shouldBe HttpStatus.CONFLICT
|
|
}
|
|
}
|
|
}
|
|
|
|
context("deleteById") {
|
|
test("이미 예약 중인 테마라면 409 예외를 던진다.") {
|
|
val themeId = 1L
|
|
|
|
every {
|
|
themeRepository.isReservedTheme(themeId)
|
|
} returns true
|
|
|
|
val exception = shouldThrow<RoomescapeException> {
|
|
themeService.deleteById(themeId)
|
|
}
|
|
|
|
assertSoftly(exception) {
|
|
this.errorType shouldBe ErrorType.THEME_IS_USED_CONFLICT
|
|
this.httpStatus shouldBe HttpStatus.CONFLICT
|
|
}
|
|
}
|
|
}
|
|
})
|