refactor: service에서의 변경 사항 테스트 반영 및 미비된 테스트 추가

This commit is contained in:
이상진 2025-07-24 09:58:04 +09:00
parent faf6e408b6
commit 31538c2632
4 changed files with 74 additions and 37 deletions

View File

@ -5,10 +5,10 @@ import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException
import roomescape.member.business.MemberService import roomescape.member.business.MemberService
import roomescape.member.infrastructure.persistence.Role import roomescape.member.infrastructure.persistence.Role
import roomescape.reservation.exception.ReservationErrorCode
import roomescape.reservation.exception.ReservationException
import roomescape.reservation.infrastructure.persistence.ReservationRepository import roomescape.reservation.infrastructure.persistence.ReservationRepository
import roomescape.theme.business.ThemeService import roomescape.theme.business.ThemeService
import roomescape.time.business.TimeService import roomescape.time.business.TimeService
@ -39,10 +39,10 @@ class ReservationServiceTest : FunSpec({
val reservationRequest = ReservationFixture.createRequest() val reservationRequest = ReservationFixture.createRequest()
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.addReservation(reservationRequest, 1L) reservationService.createConfirmedReservation(reservationRequest, 1L)
}.also { }.also {
it.errorType shouldBe ErrorType.RESERVATION_DUPLICATED it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED
} }
} }
@ -69,10 +69,10 @@ class ReservationServiceTest : FunSpec({
timeService.findById(any()) timeService.findById(any())
} returns TimeFixture.create() } returns TimeFixture.create()
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.addReservation(reservationRequest, 1L) reservationService.createConfirmedReservation(reservationRequest, 1L)
}.also { }.also {
it.errorType shouldBe ErrorType.RESERVATION_PERIOD_IN_PAST it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME
} }
} }
@ -87,10 +87,10 @@ class ReservationServiceTest : FunSpec({
startAt = LocalTime.now().minusMinutes(1) startAt = LocalTime.now().minusMinutes(1)
) )
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.addReservation(reservationRequest, 1L) reservationService.createConfirmedReservation(reservationRequest, 1L)
}.also { }.also {
it.errorType shouldBe ErrorType.RESERVATION_PERIOD_IN_PAST it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME
} }
} }
} }
@ -108,7 +108,7 @@ class ReservationServiceTest : FunSpec({
reservationRepository.exists(any()) reservationRepository.exists(any())
} returns true } returns true
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
val waitingRequest = ReservationFixture.createWaitingRequest( val waitingRequest = ReservationFixture.createWaitingRequest(
date = reservationRequest.date, date = reservationRequest.date,
themeId = reservationRequest.themeId, themeId = reservationRequest.themeId,
@ -116,7 +116,7 @@ class ReservationServiceTest : FunSpec({
) )
reservationService.createWaiting(waitingRequest, 1L) reservationService.createWaiting(waitingRequest, 1L)
}.also { }.also {
it.errorType shouldBe ErrorType.HAS_RESERVATION_OR_WAITING it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE
} }
} }
} }
@ -126,7 +126,7 @@ class ReservationServiceTest : FunSpec({
val startFrom = LocalDate.now() val startFrom = LocalDate.now()
val endAt = startFrom.minusDays(1) val endAt = startFrom.minusDays(1)
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.searchReservations( reservationService.searchReservations(
null, null,
null, null,
@ -134,7 +134,7 @@ class ReservationServiceTest : FunSpec({
endAt endAt
) )
}.also { }.also {
it.errorType shouldBe ErrorType.INVALID_DATE_RANGE it.errorCode shouldBe ReservationErrorCode.INVALID_SEARCH_DATE_RANGE
} }
} }
} }
@ -147,10 +147,10 @@ class ReservationServiceTest : FunSpec({
memberService.findById(any()) memberService.findById(any())
} returns member } returns member
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.confirmWaiting(1L, member.id!!) reservationService.confirmWaiting(1L, member.id!!)
}.also { }.also {
it.errorType shouldBe ErrorType.PERMISSION_DOES_NOT_EXIST it.errorCode shouldBe ReservationErrorCode.NO_PERMISSION
} }
} }
@ -166,10 +166,10 @@ class ReservationServiceTest : FunSpec({
reservationRepository.isExistConfirmedReservation(reservationId) reservationRepository.isExistConfirmedReservation(reservationId)
} returns true } returns true
shouldThrow<RoomescapeException> { shouldThrow<ReservationException> {
reservationService.confirmWaiting(reservationId, member.id!!) reservationService.confirmWaiting(reservationId, member.id!!)
}.also { }.also {
it.errorType shouldBe ErrorType.RESERVATION_DUPLICATED it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS
} }
} }
} }

View File

@ -48,7 +48,7 @@ class ReservationWithPaymentServiceTest : FunSpec({
context("addReservationWithPayment") { context("addReservationWithPayment") {
test("예약 및 결제 정보를 저장한다.") { test("예약 및 결제 정보를 저장한다.") {
every { every {
reservationService.addReservation(reservationCreateWithPaymentRequest, memberId) reservationService.createConfirmedReservation(reservationCreateWithPaymentRequest, memberId)
} returns reservationEntity } returns reservationEntity
every { every {

View File

@ -168,7 +168,7 @@ class ReservationRepositoryTest(
entityManager.clear() entityManager.clear()
} }
val result: List<MyReservationRetrieveResponse> = reservationRepository.findAllById(reservation.member.id!!) val result: List<MyReservationRetrieveResponse> = reservationRepository.findAllByMemberId(reservation.member.id!!)
result shouldHaveSize 1 result shouldHaveSize 1
assertSoftly(result.first()) { assertSoftly(result.first()) {
@ -179,7 +179,7 @@ class ReservationRepositoryTest(
} }
test("결제 정보가 없다면 paymentKey와 amount는 null로 반환한다.") { test("결제 정보가 없다면 paymentKey와 amount는 null로 반환한다.") {
val result: List<MyReservationRetrieveResponse> = reservationRepository.findAllById(reservation.member.id!!) val result: List<MyReservationRetrieveResponse> = reservationRepository.findAllByMemberId(reservation.member.id!!)
result shouldHaveSize 1 result shouldHaveSize 1
assertSoftly(result.first()) { assertSoftly(result.first()) {

View File

@ -19,13 +19,14 @@ import org.springframework.http.MediaType
import org.springframework.transaction.support.TransactionTemplate import org.springframework.transaction.support.TransactionTemplate
import roomescape.auth.infrastructure.jwt.JwtHandler import roomescape.auth.infrastructure.jwt.JwtHandler
import roomescape.auth.web.support.MemberIdResolver import roomescape.auth.web.support.MemberIdResolver
import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException
import roomescape.member.business.MemberService import roomescape.member.business.MemberService
import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.member.infrastructure.persistence.MemberEntity
import roomescape.member.infrastructure.persistence.Role import roomescape.member.infrastructure.persistence.Role
import roomescape.payment.exception.PaymentErrorCode
import roomescape.payment.exception.PaymentException
import roomescape.payment.infrastructure.client.TossPaymentClient import roomescape.payment.infrastructure.client.TossPaymentClient
import roomescape.payment.infrastructure.persistence.PaymentEntity import roomescape.payment.infrastructure.persistence.PaymentEntity
import roomescape.reservation.exception.ReservationErrorCode
import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationStatus import roomescape.reservation.infrastructure.persistence.ReservationStatus
import roomescape.theme.exception.ThemeErrorCode import roomescape.theme.exception.ThemeErrorCode
@ -89,10 +90,7 @@ class ReservationControllerTest(
test("결제 과정에서 발생하는 에러는 그대로 응답") { test("결제 과정에서 발생하는 에러는 그대로 응답") {
val reservationRequest = createRequest() val reservationRequest = createRequest()
val paymentException = RoomescapeException( val paymentException = PaymentException(PaymentErrorCode.PAYMENT_PROVIDER_ERROR)
ErrorType.PAYMENT_SERVER_ERROR,
HttpStatus.INTERNAL_SERVER_ERROR
)
every { every {
paymentClient.confirm(any()) paymentClient.confirm(any())
@ -105,8 +103,8 @@ class ReservationControllerTest(
}.When { }.When {
post("/reservations") post("/reservations")
}.Then { }.Then {
statusCode(paymentException.httpStatus.value()) statusCode(paymentException.errorCode.httpStatus.value())
body("errorType", equalTo(paymentException.errorType.name)) body("code", equalTo(paymentException.errorCode.errorCode))
} }
} }
@ -235,6 +233,7 @@ class ReservationControllerTest(
val startDate = LocalDate.now().plusDays(1) val startDate = LocalDate.now().plusDays(1)
val endDate = LocalDate.now() val endDate = LocalDate.now()
val expectedError = ReservationErrorCode.INVALID_SEARCH_DATE_RANGE
Given { Given {
port(port) port(port)
@ -244,8 +243,8 @@ class ReservationControllerTest(
}.When { }.When {
get("/reservations/search") get("/reservations/search")
}.Then { }.Then {
statusCode(HttpStatus.BAD_REQUEST.value()) statusCode(expectedError.httpStatus.value())
body("errorType", equalTo(ErrorType.INVALID_DATE_RANGE.name)) body("code", equalTo(expectedError.errorCode))
} }
} }
@ -501,6 +500,7 @@ class ReservationControllerTest(
themeId = reservationRequest.themeId, themeId = reservationRequest.themeId,
timeId = reservationRequest.timeId timeId = reservationRequest.timeId
) )
val expectedError = ReservationErrorCode.ALREADY_RESERVE
Given { Given {
port(port) port(port)
@ -509,8 +509,8 @@ class ReservationControllerTest(
}.When { }.When {
post("/reservations/waiting") post("/reservations/waiting")
}.Then { }.Then {
statusCode(HttpStatus.BAD_REQUEST.value()) statusCode(expectedError.httpStatus.value())
body("errorType", equalTo(ErrorType.HAS_RESERVATION_OR_WAITING.name)) body("code", equalTo(expectedError.errorCode))
} }
} }
} }
@ -544,20 +544,21 @@ class ReservationControllerTest(
} }
} }
test("이미 완료된 예약은 삭제할 수 없다.") { test("이미 확정된 예약을 삭제하면 예외 응답") {
val member = login(MemberFixture.create(role = Role.MEMBER)) val member = login(MemberFixture.create(role = Role.MEMBER))
val reservation: ReservationEntity = createSingleReservation( val reservation: ReservationEntity = createSingleReservation(
member = member, member = member,
status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED
) )
val expectedError = ReservationErrorCode.ALREADY_CONFIRMED
Given { Given {
port(port) port(port)
}.When { }.When {
delete("/reservations/waiting/{id}", reservation.id) delete("/reservations/waiting/{id}", reservation.id)
}.Then { }.Then {
body("errorType", equalTo(ErrorType.RESERVATION_NOT_FOUND.name)) statusCode(expectedError.httpStatus.value())
statusCode(HttpStatus.NOT_FOUND.value()) body("code", equalTo(expectedError.errorCode))
} }
} }
} }
@ -600,6 +601,42 @@ class ReservationControllerTest(
} ?: throw AssertionError("Reservation not found") } ?: throw AssertionError("Reservation not found")
} }
} }
test("다른 확정된 예약을 승인하면 예외 응답") {
val admin = login(MemberFixture.create(role = Role.ADMIN))
val alreadyReserved = createSingleReservation(
member = admin,
status = ReservationStatus.CONFIRMED
)
val member = MemberFixture.create(account = "account", role = Role.MEMBER).also { it ->
transactionTemplate.executeWithoutResult { _ ->
entityManager.persist(it)
}
}
val waiting = ReservationFixture.create(
date = alreadyReserved.date,
time = alreadyReserved.time,
theme = alreadyReserved.theme,
member = member,
status = ReservationStatus.WAITING
).also {
transactionTemplate.executeWithoutResult { _ ->
entityManager.persist(it)
}
}
val expectedError = ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS
Given {
port(port)
}.When {
post("/reservations/waiting/${waiting.id!!}/confirm")
}.Then {
log().all()
statusCode(expectedError.httpStatus.value())
body("code", equalTo(expectedError.errorCode))
}
}
} }
context("POST /reservations/waiting/{id}/reject") { context("POST /reservations/waiting/{id}/reject") {