diff --git a/src/test/java/roomescape/payment/business/PaymentServiceKTest.kt b/src/test/java/roomescape/payment/business/PaymentServiceKTest.kt new file mode 100644 index 00000000..e72b228c --- /dev/null +++ b/src/test/java/roomescape/payment/business/PaymentServiceKTest.kt @@ -0,0 +1,129 @@ +package roomescape.payment.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.just +import io.mockk.mockk +import io.mockk.runs +import org.springframework.http.HttpStatus +import roomescape.common.exception.ErrorType +import roomescape.common.exception.RoomescapeException +import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository +import roomescape.payment.infrastructure.persistence.PaymentRepository +import roomescape.payment.web.PaymentCancel +import roomescape.util.PaymentFixture +import java.time.OffsetDateTime + +class PaymentServiceKTest : FunSpec({ + val paymentRepository: PaymentRepository = mockk() + val canceledPaymentRepository: CanceledPaymentRepository = mockk() + + val paymentService = PaymentService(paymentRepository, canceledPaymentRepository) + + context("cancelPaymentByAdmin") { + val reservationId = 1L + test("reservationId로 paymentKey를 찾을 수 없으면 예외를 던진다.") { + every { paymentRepository.findPaymentKeyByReservationId(reservationId) } returns null + + val exception = shouldThrow { + paymentService.cancelPaymentByAdmin(reservationId) + } + + assertSoftly(exception) { + this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND + this.httpStatus shouldBe HttpStatus.NOT_FOUND + } + } + + context("reservationId로 paymentKey를 찾고난 후") { + val paymentKey = "test-payment-key" + + every { + paymentRepository.findPaymentKeyByReservationId(reservationId) + } returns paymentKey + + test("해당 paymentKey로 paymentEntity를 찾을 수 없으면 예외를 던진다.") { + every { + paymentRepository.findByPaymentKey(paymentKey) + } returns null + + val exception = shouldThrow { + paymentService.cancelPaymentByAdmin(reservationId) + } + + assertSoftly(exception) { + this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND + this.httpStatus shouldBe HttpStatus.NOT_FOUND + } + } + + test("해당 paymentKey로 paymentEntity를 찾고, cancelPaymentEntity를 저장한다.") { + val paymentEntity = PaymentFixture.create(paymentKey = paymentKey) + + every { + paymentRepository.findByPaymentKey(paymentKey) + } returns paymentEntity.also { + every { + paymentRepository.delete(it) + } just runs + } + + every { + canceledPaymentRepository.save(any()) + } returns PaymentFixture.createCanceled( + id = 1L, + paymentKey = paymentKey, + cancelAmount = paymentEntity.totalAmount, + ) + + val result: PaymentCancel.Request = paymentService.cancelPaymentByAdmin(reservationId) + + assertSoftly(result) { + this.paymentKey shouldBe paymentKey + this.amount shouldBe paymentEntity.totalAmount + this.cancelReason shouldBe "고객 요청" + } + } + } + } + + context("updateCanceledTime") { + val paymentKey = "test-payment-key" + val canceledAt = OffsetDateTime.now() + + test("paymentKey로 canceledPaymentEntity를 찾을 수 없으면 예외를 던진다.") { + every { + canceledPaymentRepository.findByPaymentKey(paymentKey) + } returns null + + val exception = shouldThrow { + paymentService.updateCanceledTime(paymentKey, canceledAt) + } + + assertSoftly(exception) { + this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND + this.httpStatus shouldBe HttpStatus.NOT_FOUND + } + } + + test("paymentKey로 canceledPaymentEntity를 찾고, canceledAt을 업데이트한다.") { + val canceledPaymentEntity = PaymentFixture.createCanceled( + paymentKey = paymentKey, + canceledAt = canceledAt.minusMinutes(1) + ) + + every { + canceledPaymentRepository.findByPaymentKey(paymentKey) + } returns canceledPaymentEntity + + paymentService.updateCanceledTime(paymentKey, canceledAt) + + assertSoftly(canceledPaymentEntity) { + this.canceledAt shouldBe canceledAt + } + } + } +})