package roomescape.reservation.business import io.kotest.assertions.assertSoftly import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.mockk.Runs import io.mockk.every import io.mockk.just import io.mockk.mockk import roomescape.payment.business.PaymentService import roomescape.payment.infrastructure.persistence.PaymentEntity import roomescape.payment.web.PaymentCancelRequest import roomescape.payment.web.toCreateResponse import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationStatus import roomescape.reservation.web.ReservationCreateWithPaymentRequest import roomescape.reservation.web.ReservationRetrieveResponse import roomescape.util.* class ReservationWithPaymentServiceTest : FunSpec({ val reservationService: ReservationService = mockk() val paymentService: PaymentService = mockk() val reservationWithPaymentService = ReservationWithPaymentService( reservationService = reservationService, paymentService = paymentService ) val reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest = ReservationFixture.createRequest() val paymentApproveResponse = PaymentFixture.createApproveResponse() val memberId = 1L val reservationEntity: ReservationEntity = ReservationFixture.create( id = 1L, date = reservationCreateWithPaymentRequest.date, time = TimeFixture.create(id = reservationCreateWithPaymentRequest.timeId), theme = ThemeFixture.create(id = reservationCreateWithPaymentRequest.themeId), member = MemberFixture.create(id = memberId), status = ReservationStatus.CONFIRMED ) val paymentEntity: PaymentEntity = PaymentFixture.create( id = 1L, orderId = reservationCreateWithPaymentRequest.orderId, paymentKey = reservationCreateWithPaymentRequest.paymentKey, totalAmount = reservationCreateWithPaymentRequest.amount, reservation = reservationEntity, ) context("addReservationWithPayment") { test("예약 및 결제 정보를 저장한다.") { every { reservationService.addReservation(reservationCreateWithPaymentRequest, memberId) } returns reservationEntity every { paymentService.createPayment(paymentApproveResponse, reservationEntity) } returns paymentEntity.toCreateResponse() val result: ReservationRetrieveResponse = reservationWithPaymentService.createReservationAndPayment( request = reservationCreateWithPaymentRequest, paymentInfo = paymentApproveResponse, memberId = memberId ) assertSoftly(result) { this.id shouldBe reservationEntity.id this.date shouldBe reservationEntity.date this.member.id shouldBe reservationEntity.member.id this.time.id shouldBe reservationEntity.time.id this.theme.id shouldBe reservationEntity.theme.id this.status shouldBe ReservationStatus.CONFIRMED } } context("removeReservationWithPayment") { test("예약 및 결제 정보를 삭제하고, 결제 취소 정보를 저장한다.") { val paymentCancelRequest: PaymentCancelRequest = PaymentFixture.createCancelRequest().copy( paymentKey = paymentEntity.paymentKey, amount = paymentEntity.totalAmount, cancelReason = "고객 요청" ) every { paymentService.createCanceledPaymentByReservationId(reservationEntity.id!!) } returns paymentCancelRequest every { reservationService.deleteReservation(reservationEntity.id!!, reservationEntity.member.id!!) } just Runs val result: PaymentCancelRequest = reservationWithPaymentService.deleteReservationAndPayment( reservationId = reservationEntity.id!!, memberId = reservationEntity.member.id!! ) result shouldBe paymentCancelRequest } } context("isNotPaidReservation") { test("결제된 예약이면 true를 반환한다.") { every { paymentService.isReservationPaid(reservationEntity.id!!) } returns false val result: Boolean = reservationWithPaymentService.isNotPaidReservation(reservationEntity.id!!) result shouldBe true } test("결제되지 않은 예약이면 false를 반환한다.") { every { paymentService.isReservationPaid(reservationEntity.id!!) } returns true val result: Boolean = reservationWithPaymentService.isNotPaidReservation(reservationEntity.id!!) result shouldBe false } } } })