diff --git a/src/test/kotlin/roomescape/payment/infrastructure/client/SampleTossPaymentConst.kt b/src/test/kotlin/roomescape/payment/infrastructure/client/SampleTossPaymentConst.kt deleted file mode 100644 index 8715c2be..00000000 --- a/src/test/kotlin/roomescape/payment/infrastructure/client/SampleTossPaymentConst.kt +++ /dev/null @@ -1,194 +0,0 @@ -package roomescape.payment.infrastructure.client - -import roomescape.payment.web.PaymentCancelRequest -import kotlin.math.roundToLong - -object SampleTossPaymentConst { - val paymentKey: String = "5EnNZRJGvaBX7zk2yd8ydw26XvwXkLrx9POLqKQjmAw4b0e1" - - val orderId: String = "MC4wODU4ODQwMzg4NDk0" - - val amount: Long = 1000L - - val paymentType: String = "카드" - - val cancelReason: String = "테스트 결제 취소" - - val paymentRequest: PaymentApproveRequest = PaymentApproveRequest( - paymentKey, - orderId, - amount, - paymentType - ) - - val paymentRequestJson: String = """ - { - "paymentKey": "$paymentKey", - "orderId": "$orderId", - "amount": $amount, - "paymentType": "$paymentType" - } - """.trimIndent() - - val cancelRequest: PaymentCancelRequest = PaymentCancelRequest( - paymentKey, - amount, - cancelReason - ) - - val cancelRequestJson: String = """ - { - "cancelReason": "$cancelReason" - } - """.trimIndent() - - val tossPaymentErrorJson: String = """ - { - "code": "ERROR_CODE", - "message": "Error message" - } - """.trimIndent() - - val confirmJson: String = """ - { - "mId": "tosspayments", - "lastTransactionKey": "9C62B18EEF0DE3EB7F4422EB6D14BC6E", - "paymentKey": "$paymentKey", - "orderId": "$orderId", - "orderName": "토스 티셔츠 외 2건", - "taxExemptionAmount": 0, - "status": "DONE", - "requestedAt": "2024-02-13T12:17:57+09:00", - "approvedAt": "2024-02-13T12:18:14+09:00", - "useEscrow": false, - "cultureExpense": false, - "card": { - "issuerCode": "71", - "acquirerCode": "71", - "number": "12345678****000*", - "installmentPlanMonths": 0, - "isInterestFree": false, - "interestPayer": null, - "approveNo": "00000000", - "useCardPoint": false, - "cardType": "신용", - "ownerType": "개인", - "acquireStatus": "READY", - "receiptUrl": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=tviva20240213121757MvuS8&ref=PX", - "amount": 1000 - }, - "virtualAccount": null, - "transfer": null, - "mobilePhone": null, - "giftCertificate": null, - "cashReceipt": null, - "cashReceipts": null, - "discount": null, - "cancels": null, - "secret": null, - "type": "NORMAL", - "easyPay": { - "provider": "토스페이", - "amount": 0, - "discountAmount": 0 - }, - "easyPayAmount": 0, - "easyPayDiscountAmount": 0, - "country": "KR", - "failure": null, - "isPartialCancelable": true, - "receipt": { - "url": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=tviva20240213121757MvuS8&ref=PX" - }, - "checkout": { - "url": "https://api.tosspayments.com/v1/payments/5EnNZRJGvaBX7zk2yd8ydw26XvwXkLrx9POLqKQjmAw4b0e1/checkout" - }, - "currency": "KRW", - "totalAmount": $amount, - "balanceAmount": $amount, - "suppliedAmount": ${(amount / 1.1).roundToLong()}, - "vat": ${amount - (amount / 1.1).roundToLong()}, - "taxFreeAmount": 0, - "method": "$paymentType", - "version": "2022-11-16" - } - """.trimIndent() - - val cancelJson: String = """ - { - "mId": "tosspayments", - "lastTransactionKey": "090A796806E726BBB929F4A2CA7DB9A7", - "paymentKey": "$paymentKey", - "orderId": "$orderId", - "orderName": "토스 티셔츠 외 2건", - "taxExemptionAmount": 0, - "status": "CANCELED", - "requestedAt": "2024-02-13T12:17:57+09:00", - "approvedAt": "2024-02-13T12:18:14+09:00", - "useEscrow": false, - "cultureExpense": false, - "card": { - "issuerCode": "71", - "acquirerCode": "71", - "number": "12345678****000*", - "installmentPlanMonths": 0, - "isInterestFree": false, - "interestPayer": null, - "approveNo": "00000000", - "useCardPoint": false, - "cardType": "신용", - "ownerType": "개인", - "acquireStatus": "READY", - "amount": 1000 - }, - "virtualAccount": null, - "transfer": null, - "mobilePhone": null, - "giftCertificate": null, - "cashReceipt": null, - "cashReceipts": null, - "discount": null, - "cancels": [ - { - "transactionKey": "090A796806E726BBB929F4A2CA7DB9A7", - "cancelReason": "$cancelReason", - "taxExemptionAmount": 0, - "canceledAt": "2024-02-13T12:20:23+09:00", - "easyPayDiscountAmount": 0, - "receiptKey": null, - "cancelAmount": $amount, - "taxFreeAmount": 0, - "refundableAmount": 0, - "cancelStatus": "DONE", - "cancelRequestId": null - } - ], - "secret": null, - "type": "NORMAL", - "easyPay": { - "provider": "토스페이", - "amount": 0, - "discountAmount": 0 - }, - "easyPayAmount": 0, - "easyPayDiscountAmount": 0, - "country": "KR", - "failure": null, - "isPartialCancelable": true, - "receipt": { - "url": "https://dashboard.tosspayments.com/receipt/redirection?transactionId=tviva20240213121757MvuS8&ref=PX" - }, - "checkout": { - "url": "https://api.tosspayments.com/v1/payments/5EnNZRJGvaBX7zk2yd8ydw26XvwXkLrx9POLqKQjmAw4b0e1/checkout" - }, - "currency": "KRW", - "totalAmount": $amount, - "balanceAmount": 0, - "suppliedAmount": 0, - "vat": 0, - "taxFreeAmount": 0, - "method": "$paymentType", - "version": "2022-11-16" - } - """.trimIndent() -} diff --git a/src/test/kotlin/roomescape/reservation/business/ReservationCommandServiceTest.kt b/src/test/kotlin/roomescape/reservation/business/ReservationCommandServiceTest.kt deleted file mode 100644 index d75b2366..00000000 --- a/src/test/kotlin/roomescape/reservation/business/ReservationCommandServiceTest.kt +++ /dev/null @@ -1,284 +0,0 @@ -package roomescape.reservation.business - -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.throwables.shouldNotThrow -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import io.mockk.* -import roomescape.reservation.exception.ReservationErrorCode -import roomescape.reservation.exception.ReservationException -import roomescape.reservation.implement.ReservationFinder -import roomescape.reservation.implement.ReservationWriter -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.util.MemberFixture -import roomescape.util.ReservationFixture -import roomescape.util.ThemeFixture -import roomescape.util.TimeFixture - -class ReservationCommandServiceTest : FunSpec({ - - val reservationFinder: ReservationFinder = mockk() - val reservationWriter: ReservationWriter = mockk() - val reservationWriteService = ReservationWriteService(reservationFinder, reservationWriter) - - context("createReservationWithPayment") { - val request = ReservationFixture.createRequest() - val memberId = 1L - - test("정상 응답") { - val createdReservation = ReservationFixture.create( - date = request.date, - time = TimeFixture.create(id = request.timeId), - theme = ThemeFixture.create(id = request.themeId), - member = MemberFixture.create(id = memberId), - status = ReservationStatus.CONFIRMED - ) - - every { - reservationWriter.create( - date = request.date, - timeId = request.timeId, - themeId = request.themeId, - status = ReservationStatus.CONFIRMED, - memberId = memberId, - requesterId = memberId - ) - } returns createdReservation - - val result = reservationWriteService.createReservationWithPayment(request, memberId) - - assertSoftly(result) { - this.date shouldBe request.date - this.time.id shouldBe request.timeId - this.theme.id shouldBe request.themeId - this.member.id shouldBe memberId - this.status shouldBe ReservationStatus.CONFIRMED - } - } - - test("예약 생성에 실패하면 예외 응답") { - every { - reservationWriter.create(any(), any(), any(), any(), any(), any()) - } throws ReservationException(ReservationErrorCode.RESERVATION_DUPLICATED) - - shouldThrow { - reservationWriteService.createReservationWithPayment(request, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED - } - } - } - - context("createReservationByAdmin") { - val request = ReservationFixture.createAdminRequest() - val adminId = request.memberId + 1 - - test("정상 응답") { - val createdReservation = ReservationFixture.create( - date = request.date, - time = TimeFixture.create(id = request.timeId), - theme = ThemeFixture.create(id = request.themeId), - member = MemberFixture.create(id = request.memberId), - status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED - ) - - every { - reservationWriter.create( - date = request.date, - timeId = request.timeId, - themeId = request.themeId, - status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED, - memberId = request.memberId, - requesterId = adminId - ) - } returns createdReservation - - val response = reservationWriteService.createReservationByAdmin(request, adminId) - - assertSoftly(response) { - this.date shouldBe request.date - this.time.id shouldBe request.timeId - this.theme.id shouldBe request.themeId - this.member.id shouldBe request.memberId - this.status shouldBe ReservationStatus.CONFIRMED_PAYMENT_REQUIRED - } - } - } - - context("createWaiting") { - val request = ReservationFixture.createWaitingRequest() - val memberId = 1L - - test("정상 응답") { - val createdWaiting = ReservationFixture.create( - date = request.date, - time = TimeFixture.create(id = request.timeId), - theme = ThemeFixture.create(id = request.themeId), - member = MemberFixture.create(id = memberId), - status = ReservationStatus.WAITING - ) - - every { - reservationWriter.create( - date = request.date, - timeId = request.timeId, - themeId = request.themeId, - status = ReservationStatus.WAITING, - memberId = memberId, - requesterId = memberId - ) - } returns createdWaiting - - val response = reservationWriteService.createWaiting(request, memberId) - - assertSoftly(response) { - this.date shouldBe request.date - this.time.id shouldBe request.timeId - this.theme.id shouldBe request.themeId - this.member.id shouldBe memberId - this.status shouldBe ReservationStatus.WAITING - } - } - - test("이미 예약한 내역이 있으면 예외 응답") { - every { - reservationWriter.create(any(), any(), any(), any(), any(), any()) - } throws ReservationException(ReservationErrorCode.ALREADY_RESERVE) - - shouldThrow { - reservationWriteService.createWaiting(request, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE - } - } - } - - context("deleteReservation") { - val reservationId = 1L - val memberId = 1L - val reservation = ReservationFixture.create(id = reservationId, member = MemberFixture.create(id = memberId)) - - test("정상 응답") { - every { reservationFinder.findById(reservationId) } returns reservation - every { reservationWriter.deleteConfirmed(reservation, memberId) } just Runs - - shouldNotThrow { - reservationWriteService.deleteReservation(reservationId, memberId) - } - - verify(exactly = 1) { reservationWriter.deleteConfirmed(reservation, memberId) } - } - - test("예약을 찾을 수 없으면 예외 응답") { - every { - reservationFinder.findById(reservationId) - } throws ReservationException(ReservationErrorCode.RESERVATION_NOT_FOUND) - - shouldThrow { - reservationWriteService.deleteReservation(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_NOT_FOUND - } - } - - test("삭제하려는 회원이 관리자가 아니고, 대기한 회원과 다르면 예외 응답") { - every { reservationFinder.findById(reservationId) } returns reservation - every { - reservationWriter.deleteConfirmed(reservation, memberId) - } throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER) - - shouldThrow { - reservationWriteService.deleteReservation(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER - } - } - } - - context("confirmWaiting") { - val reservationId = 1L - val memberId = 99L // Admin - - test("정상 응답") { - every { reservationWriter.confirm(reservationId) } just Runs - - shouldNotThrow { - reservationWriteService.confirmWaiting(reservationId, memberId) - } - - verify(exactly = 1) { reservationWriter.confirm(reservationId) } - } - - test("이미 확정된 예약이 있으면 예외 응답") { - every { - reservationWriter.confirm(reservationId) - } throws ReservationException(ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS) - - shouldThrow { - reservationWriteService.confirmWaiting(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS - } - } - } - - context("deleteWaiting") { - val reservationId = 1L - val memberId = 1L - val waitingReservation = ReservationFixture.create( - id = reservationId, - member = MemberFixture.create(id = memberId), - status = ReservationStatus.WAITING - ) - - test("정상 응답") { - every { reservationFinder.findById(reservationId) } returns waitingReservation - every { reservationWriter.deleteWaiting(waitingReservation, memberId) } just Runs - - shouldNotThrow { - reservationWriteService.deleteWaiting(reservationId, memberId) - } - - verify(exactly = 1) { reservationWriter.deleteWaiting(waitingReservation, memberId) } - } - - test("예약을 찾을 수 없으면 예외 응답") { - every { - reservationFinder.findById(reservationId) - } throws ReservationException(ReservationErrorCode.RESERVATION_NOT_FOUND) - - shouldThrow< ReservationException> { - reservationWriteService.deleteWaiting(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_NOT_FOUND - } - } - - test("대기 상태가 아니면 예외 응답") { - every { reservationFinder.findById(reservationId) } returns waitingReservation - every { - reservationWriter.deleteWaiting(waitingReservation, memberId) - } throws ReservationException(ReservationErrorCode.ALREADY_CONFIRMED) - - shouldThrow { - reservationWriteService.deleteWaiting(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_CONFIRMED - } - } - - test("삭제하려는 회원이 관리자가 아니고, 대기한 회원과 다르면 예외 응답") { - every { reservationFinder.findById(reservationId) } returns waitingReservation - every { - reservationWriter.deleteWaiting(waitingReservation, memberId) - } throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER) - - shouldThrow { - reservationWriteService.deleteWaiting(reservationId, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER - } - } - } -}) diff --git a/src/test/kotlin/roomescape/reservation/business/ReservationQueryServiceTest.kt b/src/test/kotlin/roomescape/reservation/business/ReservationQueryServiceTest.kt deleted file mode 100644 index 782b149c..00000000 --- a/src/test/kotlin/roomescape/reservation/business/ReservationQueryServiceTest.kt +++ /dev/null @@ -1,118 +0,0 @@ -package roomescape.reservation.business - -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import roomescape.reservation.exception.ReservationErrorCode -import roomescape.reservation.exception.ReservationException -import roomescape.reservation.implement.ReservationFinder -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.reservation.web.MyReservationRetrieveResponse -import roomescape.util.MemberFixture -import roomescape.util.ReservationFixture -import roomescape.util.ThemeFixture -import java.time.LocalDate - -class ReservationQueryServiceTest : FunSpec({ - - val reservationFinder: ReservationFinder = mockk() - val reservationFindService = ReservationFindService(reservationFinder) - - context("findReservations") { - test("정상 응답") { - val confirmedReservations = listOf( - ReservationFixture.create(status = ReservationStatus.CONFIRMED), - ReservationFixture.create(status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED) - ) - every { - reservationFinder.findAllByStatuses(*ReservationStatus.confirmedStatus()) - } returns confirmedReservations - - val response = reservationFindService.findReservations() - - assertSoftly(response.reservations) { - this shouldHaveSize 2 - } - } - } - - context("findAllWaiting") { - test("정상 응답") { - val waitingReservations = listOf( - ReservationFixture.create(status = ReservationStatus.WAITING), - ReservationFixture.create(status = ReservationStatus.WAITING) - ) - every { - reservationFinder.findAllByStatuses(ReservationStatus.WAITING) - } returns waitingReservations - - val response = reservationFindService.findAllWaiting() - - assertSoftly(response.reservations) { - this shouldHaveSize 2 - } - } - } - - context("findReservationsByMemberId") { - val memberId = 1L - test("정상 응답") { - val myReservations = listOf(mockk(), mockk()) - - every { - reservationFinder.findAllByMemberId(memberId) - } returns myReservations - - val response = reservationFindService.findReservationsByMemberId(memberId) - - response.reservations shouldHaveSize 2 - } - } - - context("searchReservations") { - val themeId = 1L - val memberId = 1L - val startFrom = LocalDate.now() - val endAt = LocalDate.now().plusDays(1) - - test("정상 응답") { - val searchedReservations = listOf( - ReservationFixture.create( - theme = ThemeFixture.create(themeId), - member = MemberFixture.create(memberId), - date = startFrom - ) - ) - - every { - reservationFinder.searchReservations(themeId, memberId, startFrom, endAt) - } returns searchedReservations - - val response = reservationFindService.searchReservations(themeId, memberId, startFrom, endAt) - - assertSoftly(response.reservations) { - this shouldHaveSize 1 - this[0].theme.id shouldBe themeId - this[0].member.id shouldBe memberId - this[0].date shouldBe startFrom - } - } - - test("종료 날짜가 시작 날짜 이전이면 예외 응답") { - val invalidEndAt = startFrom.minusDays(1) - every { - reservationFinder.searchReservations(themeId, memberId, startFrom, invalidEndAt) - } throws ReservationException(ReservationErrorCode.INVALID_SEARCH_DATE_RANGE) - - shouldThrow { - reservationFindService.searchReservations(themeId, memberId, startFrom, invalidEndAt) - }.also { - it.errorCode shouldBe ReservationErrorCode.INVALID_SEARCH_DATE_RANGE - } - } - } -}) diff --git a/src/test/kotlin/roomescape/reservation/implement/ReservationFinderTest.kt b/src/test/kotlin/roomescape/reservation/implement/ReservationFinderTest.kt deleted file mode 100644 index e11946d3..00000000 --- a/src/test/kotlin/roomescape/reservation/implement/ReservationFinderTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package roomescape.reservation.implement - -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 io.mockk.spyk -import io.mockk.verify -import org.springframework.data.jpa.domain.Specification -import org.springframework.data.repository.findByIdOrNull -import roomescape.reservation.exception.ReservationErrorCode -import roomescape.reservation.exception.ReservationException -import roomescape.reservation.infrastructure.persistence.ReservationEntity -import roomescape.reservation.infrastructure.persistence.ReservationRepository -import roomescape.reservation.infrastructure.persistence.ReservationSearchSpecification -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.time.exception.TimeErrorCode -import roomescape.time.exception.TimeException -import java.time.LocalDate - -class ReservationFinderTest : FunSpec({ - val reservationRepository: ReservationRepository = mockk() - val reservationValidator = ReservationValidator(reservationRepository) - - val reservationFinder = ReservationFinder(reservationRepository, reservationValidator) - - context("findById") { - val reservationId = 1L - test("동일한 ID인 시간을 찾아 응답한다.") { - every { - reservationRepository.findByIdOrNull(reservationId) - } returns mockk() - - reservationFinder.findById(reservationId) - - verify(exactly = 1) { - reservationRepository.findByIdOrNull(reservationId) - } - } - - test("동일한 ID인 시간이 없으면 실패한다.") { - every { - reservationRepository.findByIdOrNull(reservationId) - } returns null - - shouldThrow { - reservationFinder.findById(reservationId) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_NOT_FOUND - } - } - } - - context("searchReservations") { - test("시작 날짜가 종료 날짜 이전이면 실패한다.") { - shouldThrow { - reservationFinder.searchReservations(1L, 1L, LocalDate.now(), LocalDate.now().minusDays(1)) - }.also { - it.errorCode shouldBe ReservationErrorCode.INVALID_SEARCH_DATE_RANGE - } - } - } -}) diff --git a/src/test/kotlin/roomescape/reservation/implement/ReservationValidatorTest.kt b/src/test/kotlin/roomescape/reservation/implement/ReservationValidatorTest.kt deleted file mode 100644 index 878a5cc0..00000000 --- a/src/test/kotlin/roomescape/reservation/implement/ReservationValidatorTest.kt +++ /dev/null @@ -1,170 +0,0 @@ -package roomescape.reservation.implement - -import io.kotest.assertions.throwables.shouldNotThrow -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.jpa.domain.Specification -import roomescape.member.infrastructure.persistence.Role -import roomescape.reservation.exception.ReservationErrorCode -import roomescape.reservation.exception.ReservationException -import roomescape.reservation.infrastructure.persistence.ReservationEntity -import roomescape.reservation.infrastructure.persistence.ReservationRepository -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.util.MemberFixture -import roomescape.util.ReservationFixture -import roomescape.util.ThemeFixture -import roomescape.util.TimeFixture -import java.time.LocalDate -import java.time.LocalTime - -class ReservationValidatorTest : FunSpec({ - val reservationRepository: ReservationRepository = mockk() - - val reservationValidator = ReservationValidator(reservationRepository) - - context("validateIsNotPast") { - val today = LocalDate.now() - val now = LocalTime.now() - - test("입력된 날짜가 오늘 이전이면 예외를 던진다.") { - val requestDate = today.minusDays(1) - - shouldThrow { - reservationValidator.validateIsPast(requestDate, now) - }.also { - it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME - } - } - - test("오늘 날짜라도 시간이 지났다면 예외를 던진다.") { - val requestTime = now.minusMinutes(1) - - shouldThrow { - reservationValidator.validateIsPast(today, requestTime) - }.also { - it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME - } - } - } - - context("validateSearchDateRange") { - test("시작 날짜만 입력되면 종료한다.") { - shouldNotThrow { - reservationValidator.validateSearchDateRange(LocalDate.now(), null) - } - } - - test("종료 날짜만 입력되면 종료한다.") { - shouldNotThrow { - reservationValidator.validateSearchDateRange(null, LocalDate.now()) - } - } - - test("두 날짜가 같으면 종료한다.") { - shouldNotThrow { - reservationValidator.validateSearchDateRange(LocalDate.now(), LocalDate.now()) - } - } - - test("종료 날짜가 시작 날짜 이전이면 예외를 던진다.") { - shouldThrow { - reservationValidator.validateSearchDateRange(LocalDate.now(), LocalDate.now().minusDays(1)) - }.also { - it.errorCode shouldBe ReservationErrorCode.INVALID_SEARCH_DATE_RANGE - } - } - } - - context("validateIsAlreadyExists") { - test("동일한 날짜, 시간, 테마를 가지는 예약이 있으면 예외를 던진다.") { - every { - reservationRepository.exists(any>()) - } returns true - - shouldThrow { - reservationValidator.validateIsAlreadyExists( - LocalDate.now(), - TimeFixture.create(), - ThemeFixture.create() - ) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED - } - } - } - - context("validateMemberAlreadyReserve") { - test("회원이 동일한 날짜, 시간, 테마인 예약(대기)를 이미 했다면 예외를 던진다.") { - every { - reservationRepository.exists(any>()) - } returns true - - shouldThrow { - reservationValidator.validateMemberAlreadyReserve(1L, 1L, LocalDate.now(), 1L) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE - } - } - } - - context("validateIsWaiting") { - test("예약 상태가 WAITING이 아니면 예외를 던진다.") { - ReservationStatus.confirmedStatus().forEach { status -> - shouldThrow { - val reservation = ReservationFixture.create(status = status) - reservationValidator.validateIsWaiting(reservation) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_CONFIRMED - } - } - } - } - - context("validateCreateAuthority") { - test("관리자가 아니면 예외를 던진다.") { - shouldThrow { - reservationValidator.validateCreateAuthority(MemberFixture.user()) - }.also { - it.errorCode shouldBe ReservationErrorCode.NO_PERMISSION - } - } - } - - context("validateDeleteAuthority") { - test("입력된 회원이 관리자이면 종료한다.") { - shouldNotThrow { - reservationValidator.validateDeleteAuthority(mockk(), MemberFixture.admin()) - } - } - - test("입력된 회원이 관리자가 아니고, 예약한 회원과 다른 회원이면 예외를 던진다.") { - shouldThrow { - reservationValidator.validateDeleteAuthority( - ReservationFixture.create(member = MemberFixture.create(id = 1L)), - MemberFixture.create(id = 2L, role = Role.MEMBER) - ) - }.also { - it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER - } - } - } - - context("validateAlreadyConfirmed") { - val reservationId = 1L - - test("입력된 ID의 예약과 동일한 날짜, 시간, 테마를 가지는 다른 확정 예약이 있으면 예외를 던진다.") { - every { - reservationRepository.isExistConfirmedReservation(reservationId) - } returns true - - shouldThrow { - reservationValidator.validateAlreadyConfirmed(reservationId) - }.also { - it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS - } - } - } -}) diff --git a/src/test/kotlin/roomescape/reservation/implement/ReservationWriterTest.kt b/src/test/kotlin/roomescape/reservation/implement/ReservationWriterTest.kt deleted file mode 100644 index 2fe07bce..00000000 --- a/src/test/kotlin/roomescape/reservation/implement/ReservationWriterTest.kt +++ /dev/null @@ -1,246 +0,0 @@ -package roomescape.reservation.implement - -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 roomescape.member.exception.MemberErrorCode -import roomescape.member.exception.MemberException -import roomescape.member.implement.MemberFinder -import roomescape.reservation.exception.ReservationErrorCode -import roomescape.reservation.exception.ReservationException -import roomescape.reservation.infrastructure.persistence.ReservationEntity -import roomescape.reservation.infrastructure.persistence.ReservationRepository -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.theme.implement.ThemeFinder -import roomescape.time.exception.TimeErrorCode -import roomescape.time.exception.TimeException -import roomescape.time.implement.TimeFinder -import roomescape.util.MemberFixture -import roomescape.util.ThemeFixture -import roomescape.util.TimeFixture -import roomescape.util.TsidFactory -import java.time.LocalDate -import java.time.LocalTime - -class ReservationWriterTest : FunSpec({ - - val reservationValidator: ReservationValidator = mockk() - val reservationRepository: ReservationRepository = mockk() - val memberFinder: MemberFinder = mockk() - val timeFinder: TimeFinder = mockk() - val themeFinder: ThemeFinder = mockk() - - val reservationWriter = ReservationWriter( - reservationValidator, reservationRepository, memberFinder, timeFinder, themeFinder, TsidFactory - ) - - context("create") { - val today = LocalDate.now() - val timeId = 1L - val themeId = 1L - val memberId = 1L - val status = ReservationStatus.CONFIRMED - val requesterId = 1L - - test("시간을 찾을 수 없으면 실패한다.") { - every { - timeFinder.findById(any()) - } throws TimeException(TimeErrorCode.TIME_NOT_FOUND) - - shouldThrow { - reservationWriter.create(today, timeId, themeId, memberId, status, requesterId) - }.also { - it.errorCode shouldBe TimeErrorCode.TIME_NOT_FOUND - } - } - - test("이전 날짜이면 실패한다.") { - every { - timeFinder.findById(timeId) - } returns TimeFixture.create(id = timeId, startAt = LocalTime.now().plusHours(1)) - - every { - reservationValidator.validateIsPast(any(), any()) - } throws ReservationException(ReservationErrorCode.PAST_REQUEST_DATETIME) - - shouldThrow { - reservationWriter.create(today.minusDays(1), timeId, themeId, memberId, status, requesterId) - }.also { - it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME - } - } - - test("테마를 찾을 수 없으면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - - every { - themeFinder.findById(themeId) - } throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND) - - shouldThrow { - reservationWriter.create(today.plusDays(1), timeId, themeId, memberId, status, requesterId) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND - } - } - - test("회원을 찾을 수 없으면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId) - - every { - memberFinder.findById(memberId) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - - shouldThrow { - reservationWriter.create(today.plusDays(1), timeId, themeId, memberId, status, requesterId) - }.also { - it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND - } - } - - test("이미 예약이 있는 회원이 대기를 추가하면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId) - every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId) - - every { - reservationValidator.validateMemberAlreadyReserve(themeId, timeId, today, memberId) - } throws ReservationException(ReservationErrorCode.ALREADY_RESERVE) - - shouldThrow { - reservationWriter.create(today, timeId, themeId, memberId, status = ReservationStatus.WAITING, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE - } - } - - test("동일한 날짜, 시간, 테마인 예약이 이미 있으면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId) - every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId) - - every { - reservationValidator.validateIsAlreadyExists(today, any(), any()) - } throws ReservationException(ReservationErrorCode.RESERVATION_DUPLICATED) - - shouldThrow { - reservationWriter.create(today, timeId, themeId, memberId, status, memberId) - }.also { - it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED - } - } - - test("예약하려는 회원과 신청한 회원이 다를 때, 신청한 회원을 찾을 수 없으면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId) - every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId) - every { reservationValidator.validateIsAlreadyExists(today, any(), any()) } returns Unit - - every { - memberFinder.findById(memberId + 1) - } throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND) - - shouldThrow { - reservationWriter.create(today, timeId, themeId, memberId = memberId, status, requesterId = (memberId + 1)) - }.also { - it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND - } - } - - test("예약하려는 회원과 신청한 회원이 다를 때, 신청한 회원이 관리자가 아니면 실패한다.") { - every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId) - every { reservationValidator.validateIsPast(any(), any()) } returns Unit - every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId) - every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId) - every { reservationValidator.validateIsAlreadyExists(today, any(), any()) } returns Unit - - every { - memberFinder.findById(memberId + 1) - } returns MemberFixture.create(id = memberId + 1) - - every { - reservationValidator.validateCreateAuthority(any()) - } throws ReservationException(ReservationErrorCode.NO_PERMISSION) - - shouldThrow { - reservationWriter.create(today, timeId, themeId, memberId = memberId, status, requesterId = (memberId + 1)) - }.also { - it.errorCode shouldBe ReservationErrorCode.NO_PERMISSION - } - } - } - - context("deleteWaiting") { - val reservation: ReservationEntity = mockk() - val requesterId = 1L - - test("대기 상태가 아니면 실패한다.") { - every { - reservationValidator.validateIsWaiting(any()) - } throws ReservationException(ReservationErrorCode.ALREADY_CONFIRMED) - - shouldThrow { - reservationWriter.deleteWaiting(reservation, requesterId) - }.also { - it.errorCode shouldBe ReservationErrorCode.ALREADY_CONFIRMED - } - } - - test("삭제하려는 회원이 관리자가 아니고, 예약한 회원과 다르면 실패한다.") { - every { reservationValidator.validateIsWaiting(any()) } returns Unit - every { - reservationValidator.validateDeleteAuthority(any(), any()) - } throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER) - - shouldThrow { - reservationWriter.deleteWaiting(reservation, requesterId) - }.also { - it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER - } - } - } - - context("deleteConfirm") { - val reservation: ReservationEntity = mockk() - val requesterId = 1L - - test("삭제하려는 회원이 관리자가 아니고, 예약한 회원과 다르면 실패한다.") { - every { reservationValidator.validateIsWaiting(any()) } returns Unit - every { - reservationValidator.validateDeleteAuthority(any(), any()) - } throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER) - - shouldThrow { - reservationWriter.deleteConfirmed(reservation, requesterId) - }.also { - it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER - } - } - } - - context("confirm") { - val reservationId = 1L - - test("승인하려는 대기와 같은 날짜,시간,테마를 가진 확정 예약이 있으면 실패한다.") { - every { - reservationValidator.validateAlreadyConfirmed(reservationId) - } throws ReservationException(ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS) - - shouldThrow { - reservationWriter.confirm(reservationId) - }.also { - it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS - } - } - } -}) diff --git a/src/test/kotlin/roomescape/reservation/infrastructure/persistence/ReservationSearchSpecificationTest.kt b/src/test/kotlin/roomescape/reservation/infrastructure/persistence/ReservationSearchSpecificationTest.kt deleted file mode 100644 index c9cf5570..00000000 --- a/src/test/kotlin/roomescape/reservation/infrastructure/persistence/ReservationSearchSpecificationTest.kt +++ /dev/null @@ -1,195 +0,0 @@ -package roomescape.reservation.infrastructure.persistence - -import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.collections.shouldContainExactly -import io.kotest.matchers.collections.shouldHaveSize -import jakarta.persistence.EntityManager -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.time.infrastructure.persistence.TimeEntity -import roomescape.util.MemberFixture -import roomescape.util.ReservationFixture -import roomescape.util.ThemeFixture -import roomescape.util.TimeFixture -import java.time.LocalDate - -@DataJpaTest(showSql = false) -class ReservationSearchSpecificationTest( - val entityManager: EntityManager, - val reservationRepository: ReservationRepository -) : StringSpec() { - - init { - lateinit var confirmedNow: ReservationEntity - lateinit var confirmedNotPaidYesterday: ReservationEntity - lateinit var waitingTomorrow: ReservationEntity - lateinit var member: MemberEntity - lateinit var time: TimeEntity - lateinit var theme: ThemeEntity - - "동일한 테마의 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .sameThemeId(theme.id) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 3 - this shouldContainExactly listOf(confirmedNow, confirmedNotPaidYesterday, waitingTomorrow) - } - } - - "동일한 회원의 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .sameMemberId(member.id) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 3 - this shouldContainExactly listOf(confirmedNow, confirmedNotPaidYesterday, waitingTomorrow) - } - } - - "동일한 예약 시간의 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .sameTimeId(time.id) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 3 - this shouldContainExactly listOf(confirmedNow, confirmedNotPaidYesterday, waitingTomorrow) - } - } - - "동일한 날짜의 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .sameDate(LocalDate.now()) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 1 - this shouldContainExactly listOf(confirmedNow) - } - } - - "여러 상태를 입력받아 같은 상태안 예약을 조회한다." { - val spec = ReservationSearchSpecification() - .status( - ReservationStatus.CONFIRMED, - ReservationStatus.CONFIRMED_PAYMENT_REQUIRED, - ReservationStatus.WAITING - ).build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize reservationRepository.findAll().size - } - } - - "확정 상태인 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .confirmed() - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 2 - this shouldContainExactly listOf(confirmedNow, confirmedNotPaidYesterday) - } - } - - "대기 상태인 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .waiting() - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 1 - this shouldContainExactly listOf(waitingTomorrow) - } - } - - "예약 날짜가 오늘 이후인 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .dateStartFrom(LocalDate.now()) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 2 - this shouldContainExactly listOf(confirmedNow, waitingTomorrow) - } - } - - "예약 날짜가 내일 이전인 예약을 조회한다" { - val spec = ReservationSearchSpecification() - .dateEndAt(LocalDate.now().plusDays(1)) - .build() - - val results: List = reservationRepository.findAll(spec) - - assertSoftly(results) { - this shouldHaveSize 3 - this shouldContainExactly listOf(confirmedNow, confirmedNotPaidYesterday, waitingTomorrow) - } - } - - beforeTest { - member = MemberFixture.create().also { - entityManager.persist(it) - } - time = TimeFixture.create().also { - entityManager.persist(it) - } - theme = ThemeFixture.create().also { - entityManager.persist(it) - } - - confirmedNow = ReservationFixture.create( - time = time, - member = member, - theme = theme, - date = LocalDate.now(), - status = ReservationStatus.CONFIRMED - ).also { - entityManager.persist(it) - } - - confirmedNotPaidYesterday = ReservationFixture.create( - time = time, - member = member, - theme = theme, - date = LocalDate.now().minusDays(1), - status = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED - ).also { - entityManager.persist(it) - } - - waitingTomorrow = ReservationFixture.create( - time = time, - member = member, - theme = theme, - date = LocalDate.now().plusDays(1), - status = ReservationStatus.WAITING - ).also { - entityManager.persist(it) - } - - entityManager.flush() - } - } -} diff --git a/src/test/kotlin/roomescape/theme/business/ThemeServiceTest.kt b/src/test/kotlin/roomescape/theme/business/ThemeServiceTest.kt deleted file mode 100644 index b576c26b..00000000 --- a/src/test/kotlin/roomescape/theme/business/ThemeServiceTest.kt +++ /dev/null @@ -1,162 +0,0 @@ -package roomescape.theme.business - -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.throwables.shouldNotThrow -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldContainExactly -import io.kotest.matchers.shouldBe -import io.mockk.* -import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.theme.implement.ThemeFinder -import roomescape.theme.implement.ThemeWriter -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.theme.web.ThemeCreateRequest -import roomescape.theme.web.ThemeCreateResponse -import roomescape.util.ThemeFixture -import java.time.LocalDate - -class ThemeServiceTest : FunSpec({ - val themeFinder: ThemeFinder = mockk() - val themeWriter: ThemeWriter = mockk() - - val themeService = ThemeService(themeFinder, themeWriter) - - context("findThemeById") { - val themeId = 1L - - test("정상 응답") { - val theme: ThemeEntity = ThemeFixture.create(id = themeId) - every { - themeFinder.findById(themeId) - } returns theme - - theme.id shouldBe themeId - } - - test("테마를 찾을 수 없으면 예외 응답") { - every { - themeFinder.findById(themeId) - } throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND) - - shouldThrow { - themeService.findById(themeId) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND - } - } - } - - context("findThemes") { - test("정상 응답") { - val themes = listOf( - ThemeFixture.create(id = 1, name = "t1"), - ThemeFixture.create(id = 2, name = "t2") - ) - - every { - themeFinder.findAll() - } returns themes - - val response = themeService.findThemes() - - assertSoftly(response.themes) { - this.size shouldBe themes.size - it.map { theme -> theme.name } shouldContainExactly themes.map { theme -> theme.name } - } - } - } - - context("findMostReservedThemes") { - test("7일 전 부터 1일 전 까지 조회") { - val count = 10 - val startFrom = slot() - val endAt = slot() - - every { - themeFinder.findMostReservedThemes(count, capture(startFrom), capture(endAt)) - } returns emptyList() - - themeService.findMostReservedThemes(count) - - startFrom.captured shouldBe LocalDate.now().minusDays(7) - endAt.captured shouldBe LocalDate.now().minusDays(1) - } - } - - context("createTheme") { - val request = ThemeCreateRequest( - name = "New Theme", - description = "Description", - thumbnail = "http://example.com/thumbnail.jpg" - ) - - test("정상 저장") { - every { - themeWriter.create(request.name, request.description, request.thumbnail) - } returns ThemeFixture.create( - id = 1, - name = request.name, - description = request.description, - thumbnail = request.thumbnail - ) - - val response: ThemeCreateResponse = themeService.createTheme(request) - - assertSoftly(response) { - this.id shouldBe 1L - this.name shouldBe request.name - this.description shouldBe request.description - this.thumbnail shouldBe request.thumbnail - } - } - - test("중복된 이름이 있으면 예외 응답") { - every { - themeWriter.create(request.name, request.description, request.thumbnail) - } throws ThemeException(ThemeErrorCode.THEME_NAME_DUPLICATED) - - shouldThrow { - themeService.createTheme(request) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NAME_DUPLICATED - } - } - } - - context("deleteById") { - val themeId = 1L - val theme: ThemeEntity = ThemeFixture.create(id = themeId) - - test("정상 응답") { - every { themeFinder.findById(themeId) } returns theme - every { themeWriter.delete(theme) } just Runs - - shouldNotThrow { - themeService.deleteTheme(themeId) - } - } - - test("테마를 찾을 수 없으면 예외 응답") { - every { themeFinder.findById(themeId) } throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND) - - shouldThrow { - themeService.deleteTheme(themeId) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND - } - } - - test("예약이 있는 테마이면 예외 응답") { - every { themeFinder.findById(themeId) } returns theme - every { themeWriter.delete(theme) } throws ThemeException(ThemeErrorCode.THEME_ALREADY_RESERVED) - - shouldThrow { - themeService.deleteTheme(themeId) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_ALREADY_RESERVED - } - } - } -}) diff --git a/src/test/kotlin/roomescape/theme/implement/ThemeFinderTest.kt b/src/test/kotlin/roomescape/theme/implement/ThemeFinderTest.kt deleted file mode 100644 index c41ef15a..00000000 --- a/src/test/kotlin/roomescape/theme/implement/ThemeFinderTest.kt +++ /dev/null @@ -1,76 +0,0 @@ -package roomescape.theme.implement - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldHaveSize -import io.kotest.matchers.shouldBe -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify -import org.springframework.data.repository.findByIdOrNull -import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.theme.infrastructure.persistence.ThemeRepository -import roomescape.util.ThemeFixture -import java.time.LocalDate - -class ThemeFinderTest : FunSpec({ - val themeRepository: ThemeRepository = mockk() - - val themeFinder = ThemeFinder(themeRepository) - - context("findAll") { - test("모든 테마를 조회한다.") { - every { - themeRepository.findAll() - } returns listOf(mockk(), mockk(), mockk()) - - themeRepository.findAll() shouldHaveSize 3 - } - } - - context("findById") { - val timeId = 1L - test("동일한 ID인 테마를 찾아 응답한다.") { - every { - themeRepository.findByIdOrNull(timeId) - } returns mockk() - - themeFinder.findById(timeId) - - verify(exactly = 1) { - themeRepository.findByIdOrNull(timeId) - } - } - - test("동일한 ID인 테마가 없으면 실패한다.") { - every { - themeRepository.findByIdOrNull(timeId) - } returns null - - shouldThrow { - themeFinder.findById(timeId) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND - } - } - } - - context("findMostReservedThemes") { - test("입력된 개수보다 조회된 개수가 작으면 조회된 개수만큼 반환한다.") { - val count = 10 - val startFrom = LocalDate.now().minusDays(7) - val endAt = LocalDate.now().minusDays(1) - - every { - themeRepository.findPopularThemes(startFrom, endAt, count) - } returns listOf( - ThemeFixture.create(id = 1, name = "name1"), - ThemeFixture.create(id = 2, name = "name2"), - ThemeFixture.create(id = 3, name = "name3"), - ) - - themeFinder.findMostReservedThemes(count, startFrom, endAt) shouldHaveSize 3 - } - } -}) diff --git a/src/test/kotlin/roomescape/theme/implement/ThemeValidatorTest.kt b/src/test/kotlin/roomescape/theme/implement/ThemeValidatorTest.kt deleted file mode 100644 index 175028dd..00000000 --- a/src/test/kotlin/roomescape/theme/implement/ThemeValidatorTest.kt +++ /dev/null @@ -1,79 +0,0 @@ -package roomescape.theme.implement - -import io.kotest.assertions.throwables.shouldNotThrow -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 roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.theme.infrastructure.persistence.ThemeRepository -import roomescape.util.ThemeFixture - -class ThemeValidatorTest : FunSpec({ - val themeRepository: ThemeRepository = mockk() - - val themeValidator = ThemeValidator(themeRepository) - - context("validateNameAlreadyExists") { - val name = "name" - - test("같은 이름을 가진 테마가 있으면 예외를 던진다.") { - every { - themeRepository.existsByName(name) - } returns true - - shouldThrow { - themeValidator.validateNameAlreadyExists(name) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NAME_DUPLICATED - } - } - - test("같은 이름을 가진 테마가 없으면 종료한다.") { - every { - themeRepository.existsByName(name) - } returns false - - shouldNotThrow { - themeValidator.validateNameAlreadyExists(name) - } - } - } - - context("validateIsReserved") { - test("입력된 id가 null 이면 예외를 던진다.") { - shouldThrow { - themeValidator.validateIsReserved(ThemeFixture.create(id = null)) - }.also { - it.errorCode shouldBe ThemeErrorCode.INVALID_REQUEST_VALUE - } - } - - val theme: ThemeEntity = ThemeFixture.create(id = 1L, name = "name") - - test("예약이 있는 테마이면 예외를 던진다.") { - every { - themeRepository.isReservedTheme(theme.id!!) - } returns true - - shouldThrow { - themeValidator.validateIsReserved(theme) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_ALREADY_RESERVED - } - } - - test("예약이 없는 테마이면 종료한다.") { - every { - themeRepository.isReservedTheme(theme.id!!) - } returns false - - shouldNotThrow { - themeValidator.validateIsReserved(theme) - } - } - } -}) diff --git a/src/test/kotlin/roomescape/theme/implement/ThemeWriterTest.kt b/src/test/kotlin/roomescape/theme/implement/ThemeWriterTest.kt deleted file mode 100644 index eacfd714..00000000 --- a/src/test/kotlin/roomescape/theme/implement/ThemeWriterTest.kt +++ /dev/null @@ -1,86 +0,0 @@ -package roomescape.theme.implement - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.shouldBe -import io.mockk.* -import roomescape.common.config.next -import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.theme.infrastructure.persistence.ThemeRepository -import roomescape.util.ThemeFixture -import roomescape.util.TsidFactory - -class ThemeWriterTest : FunSpec({ - - val themeValidator: ThemeValidator = mockk() - val themeRepository: ThemeRepository = mockk() - - val themeWriter = ThemeWriter(themeValidator, themeRepository, TsidFactory) - - context("create") { - val name = "name" - val description = "description" - val thumbnail = "thumbnail" - - test("중복된 이름이 있으면 실패한다.") { - every { - themeValidator.validateNameAlreadyExists(name) - } throws ThemeException(ThemeErrorCode.THEME_NAME_DUPLICATED) - - shouldThrow { - themeWriter.create(name, description, thumbnail) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_NAME_DUPLICATED - } - } - - test("중복된 이름이 없으면 저장한다.") { - every { - themeValidator.validateNameAlreadyExists(name) - } just Runs - - every { - themeRepository.save(any()) - } returns ThemeFixture.create(name = name, description = description, thumbnail = thumbnail) - - themeWriter.create(name, description, thumbnail) - - verify(exactly = 1) { - themeRepository.save(any()) - } - } - } - - context("delete") { - val theme: ThemeEntity = ThemeFixture.create(id = TsidFactory.next()) - test("예약이 있는 테마이면 실패한다.") { - every { - themeValidator.validateIsReserved(theme) - } throws ThemeException(ThemeErrorCode.THEME_ALREADY_RESERVED) - - shouldThrow { - themeWriter.delete(theme) - }.also { - it.errorCode shouldBe ThemeErrorCode.THEME_ALREADY_RESERVED - } - } - - test("예약이 없는 테마이면 제거한다.") { - every { - themeValidator.validateIsReserved(theme) - } just Runs - - every { - themeRepository.delete(theme) - } just Runs - - themeWriter.delete(theme) - - verify(exactly = 1) { - themeRepository.delete(theme) - } - } - } -}) diff --git a/src/test/kotlin/roomescape/theme/infrastructure/persistence/ThemeRepositoryTest.kt b/src/test/kotlin/roomescape/theme/infrastructure/persistence/ThemeRepositoryTest.kt deleted file mode 100644 index 6b8e6aa8..00000000 --- a/src/test/kotlin/roomescape/theme/infrastructure/persistence/ThemeRepositoryTest.kt +++ /dev/null @@ -1,144 +0,0 @@ -package roomescape.theme.infrastructure.persistence - -import io.kotest.core.spec.style.FunSpec -import io.kotest.matchers.collections.shouldContainInOrder -import io.kotest.matchers.shouldBe -import jakarta.persistence.EntityManager -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import roomescape.theme.util.TestThemeDataHelper -import java.time.LocalDate - -@DataJpaTest(showSql = false) -class ThemeRepositoryTest( - val themeRepository: ThemeRepository, - val entityManager: EntityManager -) : FunSpec() { - - val helper = TestThemeDataHelper(entityManager, transactionTemplate = null) - - init { - context("findTopNThemeBetweenStartDateAndEndDate") { - beforeTest { - for (i in 1..10) { - helper.createThemeWithReservations( - name = "테마$i", - reservedCount = i, - date = LocalDate.now().minusDays(i.toLong()), - ) - } - } - - test("지난 10일간 예약 수가 가장 많은 테마 5개를 조회") { - themeRepository.findPopularThemes( - LocalDate.now().minusDays(10), - LocalDate.now().minusDays(1), - 5 - ).also { themes -> - themes.size shouldBe 5 - themes.map { it.name } shouldContainInOrder listOf( - "테마10", "테마9", "테마8", "테마7", "테마6" - ) - } - } - - test("8일 전부터 5일 전까지 예약 수가 가장 많은 테마 3개를 조회") { - themeRepository.findPopularThemes( - LocalDate.now().minusDays(8), - LocalDate.now().minusDays(5), - 3 - ).also { themes -> - themes.size shouldBe 3 - themes.map { it.name } shouldContainInOrder listOf( - "테마8", "테마7", "테마6" - ) - } - } - - test("예약 수가 동일하면 먼저 생성된 테마를 우선 조회") { - helper.createThemeWithReservations( - name = "테마11", - reservedCount = 5, - date = LocalDate.now().minusDays(5), - ) - - themeRepository.findPopularThemes( - LocalDate.now().minusDays(6), - LocalDate.now().minusDays(4), - 5 - ).also { themes -> - themes.size shouldBe 4 - themes.map { it.name } shouldContainInOrder listOf( - "테마6", "테마5", "테마11", "테마4" - ) - } - } - - test("입력된 갯수보다 조회된 갯수가 작으면, 조회된 갯수만큼 반환") { - themeRepository.findPopularThemes( - LocalDate.now().minusDays(10), - LocalDate.now().minusDays(6), - 10 - ).also { themes -> - themes.size shouldBe 5 - } - } - - test("입력된 갯수보다 조회된 갯수가 많으면, 입력된 갯수만큼 반환") { - themeRepository.findPopularThemes( - LocalDate.now().minusDays(10), - LocalDate.now().minusDays(1), - 15 - ).also { themes -> - themes.size shouldBe 10 - } - } - - test("입력된 날짜 범위에 예약된 테마가 없을 경우 빈 리스트 반환") { - themeRepository.findPopularThemes( - LocalDate.now().plusDays(1), - LocalDate.now().plusDays(10), - 5 - ).also { themes -> - themes.size shouldBe 0 - } - } - } - context("existsByName ") { - val themeName = "test-theme" - beforeTest { - helper.createThemeWithReservations( - name = themeName, - reservedCount = 0, - date = LocalDate.now() - ) - } - test("테마 이름이 존재하면 true 반환") { - themeRepository.existsByName(themeName) shouldBe true - } - - test("테마 이름이 존재하지 않으면 false 반환") { - themeRepository.existsByName(themeName.repeat(2)) shouldBe false - } - } - - context("isReservedTheme") { - test("테마가 예약 중이면 true 반환") { - val theme = helper.createThemeWithReservations( - name = "예약된 테마", - reservedCount = 1, - date = LocalDate.now() - ) - themeRepository.isReservedTheme(theme.id!!) shouldBe true - } - - test("테마가 예약 중이 아니면 false 반환") { - val theme = helper.createThemeWithReservations( - name = "예약되지 않은 테마", - reservedCount = 0, - date = LocalDate.now() - ) - themeRepository.isReservedTheme(theme.id!!) shouldBe false - } - } - } -} diff --git a/src/test/kotlin/roomescape/theme/util/TestThemeDataHelper.kt b/src/test/kotlin/roomescape/theme/util/TestThemeDataHelper.kt deleted file mode 100644 index 9df5f6a3..00000000 --- a/src/test/kotlin/roomescape/theme/util/TestThemeDataHelper.kt +++ /dev/null @@ -1,57 +0,0 @@ -package roomescape.theme.util - -import jakarta.persistence.EntityManager -import org.springframework.transaction.support.TransactionTemplate -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.time.infrastructure.persistence.TimeEntity -import roomescape.util.MemberFixture -import roomescape.util.ReservationFixture -import roomescape.util.ThemeFixture -import roomescape.util.TimeFixture -import java.time.LocalDate -import java.time.LocalTime - -class TestThemeDataHelper( - val entityManager: EntityManager, - val transactionTemplate: TransactionTemplate? -) { - /** - * GET /themes/most-reserved-last-week API와 관련 Repository 테스트에 사용 - * @param name: 테마 이름 - * @param reservedCount: 이 테마가 예약된 횟수 - * @param date: reservedCount 개의 예약을 만들 때 사용할 날짜 - */ - fun createThemeWithReservations(name: String, reservedCount: Int, date: LocalDate): ThemeEntity = - if (transactionTemplate == null) { - createAndGet(name, reservedCount, date) - } else { - transactionTemplate.execute { createAndGet(name, reservedCount, date) }!! - } - - - fun createAndGet(name: String, reservedCount: Int, date: LocalDate): ThemeEntity { - val themeEntity: ThemeEntity = ThemeFixture.create(name = name).also { entityManager.persist(it) } - val member: MemberEntity = MemberFixture.create().also { entityManager.persist(it) } - - for (i in 1..reservedCount) { - val time: TimeEntity = TimeFixture.create( - startAt = LocalTime.now().plusMinutes(i.toLong()) - ).also { entityManager.persist(it) } - - ReservationFixture.create( - date = date, - theme = themeEntity, - member = member, - time = time, - status = ReservationStatus.entries.random() - ).also { entityManager.persist(it) } - } - - entityManager.flush() - entityManager.clear() - - return themeEntity - } -} diff --git a/src/test/kotlin/roomescape/theme/web/MostReservedThemeApiTest.kt b/src/test/kotlin/roomescape/theme/web/MostReservedThemeApiTest.kt deleted file mode 100644 index b29a4bba..00000000 --- a/src/test/kotlin/roomescape/theme/web/MostReservedThemeApiTest.kt +++ /dev/null @@ -1,110 +0,0 @@ -package roomescape.theme.web - -import io.kotest.core.spec.style.FunSpec -import io.restassured.module.kotlin.extensions.Given -import io.restassured.module.kotlin.extensions.Then -import io.restassured.module.kotlin.extensions.When -import jakarta.persistence.EntityManager -import org.hamcrest.Matchers.equalTo -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.web.server.LocalServerPort -import org.springframework.transaction.support.TransactionTemplate -import roomescape.theme.util.TestThemeDataHelper -import roomescape.util.CleanerMode -import roomescape.util.DatabaseCleanerExtension -import java.time.LocalDate -import kotlin.random.Random - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -class MostReservedThemeApiTest( - @LocalServerPort val port: Int, - val transactionTemplate: TransactionTemplate, - val entityManager: EntityManager, -) : FunSpec({ extension(DatabaseCleanerExtension(mode = CleanerMode.AFTER_SPEC)) }) { - - val helper = TestThemeDataHelper(entityManager, transactionTemplate) - - init { - beforeSpec { - transactionTemplate.executeWithoutResult { - // 7일 전 ~ 1일 전 예약된 테마 10개 생성 - for (i in 1..10) { - helper.createThemeWithReservations( - name = "테마$i", - reservedCount = 1, - date = LocalDate.now().minusDays(Random.nextLong(1, 7)) - ) - } - - // 8일 전 예약된 테마 1개 생성 - helper.createThemeWithReservations( - name = "테마11", - reservedCount = 1, - date = LocalDate.now().minusDays(8) - ) - - // 당일 예약된 테마 1개 생성 - helper.createThemeWithReservations( - name = "테마12", - reservedCount = 1, - date = LocalDate.now() - ) - } - } - - context("GET /themes/most-reserved-last-week") { - val endpoint = "/themes/most-reserved-last-week" - - test("count 파라미터가 없으면 10개를 반환한다") { - Given { - port(port) - } When { - get(endpoint) - } Then { - statusCode(200) - body("data.themes.size()", equalTo(10)) - } - } - - test("조회된 테마가 count보다 적으면 조회된 만큼 반환한다") { - val count = 15 - Given { - port(port) - param("count", count) - } When { - get(endpoint) - } Then { - statusCode(200) - body("data.themes.size()", equalTo(10)) - } - } - - test("조회된 테마가 count보다 많으면 count만큼 반환한다") { - val count = 5 - Given { - port(port) - param("count", count) - } When { - get(endpoint) - } Then { - statusCode(200) - body("data.themes.size()", equalTo(count)) - } - } - - test("지난 7일 동안의 예약만 집계한다") { - // beforeSpec 에서 정의한 테스트 데이터 중, 8일 전 / 당일 예약 테마는 제외되어야 한다. - val count = 12 - Given { - port(port) - param("count", count) - } When { - get(endpoint) - } Then { - statusCode(200) - body("data.themes.size()", equalTo(10)) - } - } - } - } -} diff --git a/src/test/kotlin/roomescape/theme/web/ThemeControllerTest.kt b/src/test/kotlin/roomescape/theme/web/ThemeControllerTest.kt deleted file mode 100644 index 8fb1745a..00000000 --- a/src/test/kotlin/roomescape/theme/web/ThemeControllerTest.kt +++ /dev/null @@ -1,278 +0,0 @@ -package roomescape.theme.web - -import com.ninjasquad.springmockk.MockkBean -import io.mockk.every -import org.hamcrest.Matchers.equalTo -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest -import org.springframework.http.MediaType -import org.springframework.test.web.servlet.MockMvc -import roomescape.auth.exception.AuthErrorCode -import roomescape.common.exception.CommonErrorCode -import roomescape.theme.business.ThemeService -import roomescape.theme.exception.ThemeErrorCode -import roomescape.theme.exception.ThemeException -import roomescape.util.RoomescapeApiTest -import roomescape.util.ThemeFixture - -@WebMvcTest(ThemeController::class) -class ThemeControllerTest(val mockMvc: MockMvc) : RoomescapeApiTest() { - @MockkBean - private lateinit var themeService: ThemeService - - init { - Given("GET /themes 요청을") { - val endpoint = "/themes" - - When("로그인 하지 않은 사용자가 보내면") { - doNotLogin() - - Then("예외 응답") { - val expectedError = AuthErrorCode.MEMBER_NOT_FOUND - runGetTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - }.andExpect { - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - } - - When("로그인 상태라면") { - loginAsUser() - - Then("정상 응답") { - every { - themeService.findThemes() - } returns listOf( - ThemeFixture.create(id = 1, name = "theme1"), - ThemeFixture.create(id = 2, name = "theme2"), - ThemeFixture.create(id = 3, name = "theme3") - ).toRetrieveListResponse() - - runGetTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isOk() } - content { - contentType(MediaType.APPLICATION_JSON) - jsonPath("$.data.themes[0].id") { value(1) } - jsonPath("$.data.themes[1].id") { value(2) } - jsonPath("$.data.themes[2].id") { value(3) } - } - } - } - } - } - - Given("POST /themes 요청을") { - val endpoint = "/themes" - val request = ThemeCreateRequest( - name = "theme1", - description = "description1", - thumbnail = "http://example.com/thumbnail1.jpg" - ) - - When("로그인 하지 않은 사용자가 보내면") { - doNotLogin() - - Then("예외 응답") { - val expectedError = AuthErrorCode.MEMBER_NOT_FOUND - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedError.errorCode)) - } - } - } - - When("관리자가 아닌 사용자가 보내면") { - loginAsUser() - - Then("예외 응답") { - val expectedError = AuthErrorCode.ACCESS_DENIED - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - } - - When("관리자가 보낼 때") { - beforeTest { - loginAsAdmin() - } - - Then("동일한 이름의 테마가 있으면 예외 응답") { - val expectedError = ThemeErrorCode.THEME_NAME_DUPLICATED - - every { - themeService.createTheme(request) - } throws ThemeException(expectedError) - - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - - When("입력 값의 형식이 잘못되면 예외 응답") { - val request = ThemeCreateRequest( - name = "theme1", - description = "description1", - thumbnail = "http://example.com/thumbnail1.jpg" - ) - - fun runTest(request: ThemeCreateRequest) { - val expectedError = CommonErrorCode.INVALID_INPUT_VALUE - - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - - Then("이름이 공백인 경우") { - val invalidRequest = request.copy(name = " ") - runTest(invalidRequest) - } - - Then("이름이 20글자를 초과하는 경우") { - val invalidRequest = request.copy(name = "a".repeat(21)) - runTest(invalidRequest) - } - - Then("설명이 공백인 경우") { - val invalidRequest = request.copy(description = " ") - runTest(invalidRequest) - } - - Then("설명이 100글자를 초과하는 경우") { - val invalidRequest = request.copy(description = "a".repeat(101)) - runTest(invalidRequest) - } - - Then("썸네일이 공백인 경우") { - val invalidRequest = request.copy(thumbnail = " ") - runTest(invalidRequest) - } - - Then("썸네일이 URL 형식이 아닌 경우") { - val invalidRequest = request.copy(thumbnail = "invalid-url") - runTest(invalidRequest) - } - } - - Then("정상 응답") { - val theme = ThemeFixture.create( - id = 1, - name = request.name, - description = request.description, - thumbnail = request.thumbnail - ) - - every { - themeService.createTheme(request) - } returns theme.toCreateResponse() - - runPostTest( - mockMvc = mockMvc, - endpoint = endpoint, - body = request, - ) { - status { isCreated() } - header { - string("Location", "/themes/${theme.id}") - } - jsonPath("$.data.id") { value(theme.id) } - jsonPath("$.data.name") { value(theme.name) } - jsonPath("$.data.description") { value(theme.description) } - jsonPath("$.data.thumbnail") { value(theme.thumbnail) } - } - } - } - } - - Given("DELETE /themes/{id} 요청을") { - val themeId = 1L - val endpoint = "/themes/$themeId" - - When("관리자가 아닌 사용자가 보내면 예외 응답") { - Then("로그인 하지 않은 경우") { - doNotLogin() - - val expectedError = AuthErrorCode.MEMBER_NOT_FOUND - runDeleteTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedError.errorCode)) - } - } - - Then("로그인은 하였으나 관리자가 아닌 경우") { - loginAsUser() - - val expectedError = AuthErrorCode.ACCESS_DENIED - runDeleteTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code", equalTo(expectedError.errorCode)) - } - } - } - - When("관리자가 보낼 때") { - beforeTest { - loginAsAdmin() - } - - Then("이미 예약된 테마이면 예외 응답") { - val expectedError = ThemeErrorCode.THEME_ALREADY_RESERVED - every { - themeService.deleteTheme(themeId) - } throws ThemeException(expectedError) - - runDeleteTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isEqualTo(expectedError.httpStatus.value()) } - jsonPath("$.code") { value(expectedError.errorCode) } - } - } - - Then("정상 응답") { - every { themeService.deleteTheme(themeId) } returns Unit - - runDeleteTest( - mockMvc = mockMvc, - endpoint = endpoint, - ) { - status { isNoContent() } - } - } - } - } - } -} diff --git a/src/test/kotlin/roomescape/util/Fixtures.kt b/src/test/kotlin/roomescape/util/Fixtures.kt index 8c74a3da..d1a738d5 100644 --- a/src/test/kotlin/roomescape/util/Fixtures.kt +++ b/src/test/kotlin/roomescape/util/Fixtures.kt @@ -1,204 +1,51 @@ package roomescape.util -import com.github.f4b6a3.tsid.TsidFactory -import roomescape.auth.infrastructure.jwt.JwtHandler -import roomescape.auth.web.LoginRequest -import roomescape.common.config.next import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.member.infrastructure.persistence.Role -import roomescape.payment.infrastructure.client.PaymentApproveRequest -import roomescape.payment.infrastructure.client.PaymentApproveResponse -import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity -import roomescape.payment.infrastructure.persistence.PaymentEntity -import roomescape.payment.web.PaymentCancelRequest -import roomescape.payment.web.PaymentCancelResponse -import roomescape.reservation.infrastructure.persistence.ReservationEntity -import roomescape.reservation.infrastructure.persistence.ReservationStatus -import roomescape.reservation.web.AdminReservationCreateRequest -import roomescape.reservation.web.ReservationCreateWithPaymentRequest -import roomescape.reservation.web.WaitingCreateRequest -import roomescape.theme.infrastructure.persistence.ThemeEntity -import roomescape.time.infrastructure.persistence.TimeEntity +import roomescape.schedule.web.ScheduleCreateRequest +import roomescape.theme.infrastructure.persistence.v2.Difficulty +import roomescape.theme.web.ThemeCreateRequestV2 import java.time.LocalDate import java.time.LocalTime -import java.time.OffsetDateTime -val TsidFactory: TsidFactory = TsidFactory(0) - -object MemberFixture { - const val NOT_LOGGED_IN_USERID: Long = 0 - - fun create( - id: Long? = TsidFactory.next(), - name: String = "sangdol", - account: String = "default", - password: String = "password", - role: Role = Role.ADMIN - ): MemberEntity = MemberEntity(id, name, "$account@email.com", password, role) - - fun admin(): MemberEntity = create( - id = 2L, - account = "admin", +object MemberFixtureV2 { + val admin: MemberEntity = MemberEntity( + _id = 9304, + name = "ADMIN", + email = "admin@example.com", + password = "adminPassword", role = Role.ADMIN ) - fun adminLoginRequest(): LoginRequest = LoginRequest( - email = admin().email, - password = admin().password - ) - - fun user(): MemberEntity = create( - id = 1L, - account = "user", + val user: MemberEntity = MemberEntity( + _id = 9305, + name = "USER", + email = "user@example.com", + password = "userPassword", role = Role.MEMBER ) +} - fun userLoginRequest(): LoginRequest = LoginRequest( - email = user().email, - password = user().password +object ThemeFixtureV2 { + val createRequest: ThemeCreateRequestV2 = ThemeCreateRequestV2( + name = "Matilda Green", + description = "constituto", + thumbnailUrl = "https://duckduckgo.com/?q=mediocrem", + difficulty = Difficulty.VERY_EASY, + price = 10000, + minParticipants = 3, + maxParticipants = 5, + availableMinutes = 80, + expectedMinutesFrom = 60, + expectedMinutesTo = 70, + isOpen = true ) } -object TimeFixture { - fun create( - id: Long? = TsidFactory.next(), - startAt: LocalTime = LocalTime.now().plusHours(1), - ): TimeEntity = TimeEntity(id, startAt) -} - -object ThemeFixture { - fun create( - id: Long? = TsidFactory.next(), - name: String = "Default Theme", - description: String = "Default Description", - thumbnail: String = "https://example.com/default-thumbnail.jpg" - ): ThemeEntity = ThemeEntity(id, name, description, thumbnail) -} - -object ReservationFixture { - fun create( - id: Long? = TsidFactory.next(), - date: LocalDate = LocalDate.now().plusWeeks(1), - theme: ThemeEntity = ThemeFixture.create(), - time: TimeEntity = TimeFixture.create(), - member: MemberEntity = MemberFixture.create(), - status: ReservationStatus = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED - ): ReservationEntity = ReservationEntity(id, date, time, theme, member, status) - - fun createRequest( - date: LocalDate = LocalDate.now().plusWeeks(1), - themeId: Long = 1L, - timeId: Long = 1L, - paymentKey: String = "paymentKey", - orderId: String = "orderId", - amount: Long = 10000L, - paymentType: String = "NORMAL", - ): ReservationCreateWithPaymentRequest = ReservationCreateWithPaymentRequest( - date = date, - timeId = timeId, - themeId = themeId, - paymentKey = paymentKey, - orderId = orderId, - amount = amount, - paymentType = paymentType - ) - - fun createAdminRequest( - date: LocalDate = LocalDate.now().plusWeeks(1), - themeId: Long = 1L, - timeId: Long = 1L, - memberId: Long = 1L - ): AdminReservationCreateRequest = AdminReservationCreateRequest( - date = date, - timeId = timeId, - themeId = themeId, - memberId = memberId - ) - - fun createWaitingRequest( - date: LocalDate = LocalDate.now().plusWeeks(1), - themeId: Long = 1L, - timeId: Long = 1L - ): WaitingCreateRequest = WaitingCreateRequest( - date = date, - timeId = timeId, - themeId = themeId +object ScheduleFixture { + val createRequest: ScheduleCreateRequest = ScheduleCreateRequest( + date = LocalDate.now().plusDays(1), + time = LocalTime.now(), + themeId = 1L ) } - -object JwtFixture { - const val SECRET_KEY_STRING: String = "daijawligagaf@LIJ$@U)9nagnalkkgalijaddljfi" - const val EXPIRATION_TIME: Long = 1000 * 60 * 60 - - fun create( - secretKey: String = SECRET_KEY_STRING, - expirationTime: Long = EXPIRATION_TIME - ): JwtHandler = JwtHandler(secretKey, expirationTime) -} - -object PaymentFixture { - const val PAYMENT_KEY: String = "paymentKey" - const val ORDER_ID: String = "orderId" - const val AMOUNT: Long = 10000L - - fun create( - id: Long? = TsidFactory.next(), - orderId: String = ORDER_ID, - paymentKey: String = PAYMENT_KEY, - totalAmount: Long = AMOUNT, - reservation: ReservationEntity = ReservationFixture.create(id = 1L), - approvedAt: OffsetDateTime = OffsetDateTime.now() - ): PaymentEntity = PaymentEntity( - _id = id, - orderId = orderId, - paymentKey = paymentKey, - totalAmount = totalAmount, - reservation = reservation, - approvedAt = approvedAt - ) - - fun createCanceled( - id: Long? = TsidFactory.next(), - paymentKey: String = PAYMENT_KEY, - cancelReason: String = "Test Cancel", - cancelAmount: Long = AMOUNT, - approvedAt: OffsetDateTime = OffsetDateTime.now(), - canceledAt: OffsetDateTime = approvedAt.plusHours(1) - ): CanceledPaymentEntity = CanceledPaymentEntity( - _id = id, - paymentKey = paymentKey, - cancelReason = cancelReason, - cancelAmount = cancelAmount, - approvedAt = approvedAt, - canceledAt = canceledAt - - ) - - fun createApproveRequest(): PaymentApproveRequest = PaymentApproveRequest( - paymentKey = PAYMENT_KEY, - orderId = ORDER_ID, - amount = AMOUNT, - paymentType = "CARD" - ) - - fun createApproveResponse(): PaymentApproveResponse = PaymentApproveResponse( - paymentKey = PAYMENT_KEY, - orderId = ORDER_ID, - approvedAt = OffsetDateTime.now(), - totalAmount = AMOUNT - ) - - fun createCancelRequest(): PaymentCancelRequest = PaymentCancelRequest( - paymentKey = PAYMENT_KEY, - amount = AMOUNT, - cancelReason = "Test Cancel" - ) - - fun createCancelResponse(): PaymentCancelResponse = PaymentCancelResponse( - cancelStatus = "SUCCESS", - cancelReason = "Test Cancel", - cancelAmount = AMOUNT, - canceledAt = OffsetDateTime.now().plusMinutes(1) - ) -} - diff --git a/src/test/kotlin/roomescape/util/FixturesV2.kt b/src/test/kotlin/roomescape/util/FixturesV2.kt deleted file mode 100644 index d1a738d5..00000000 --- a/src/test/kotlin/roomescape/util/FixturesV2.kt +++ /dev/null @@ -1,51 +0,0 @@ -package roomescape.util - -import roomescape.member.infrastructure.persistence.MemberEntity -import roomescape.member.infrastructure.persistence.Role -import roomescape.schedule.web.ScheduleCreateRequest -import roomescape.theme.infrastructure.persistence.v2.Difficulty -import roomescape.theme.web.ThemeCreateRequestV2 -import java.time.LocalDate -import java.time.LocalTime - -object MemberFixtureV2 { - val admin: MemberEntity = MemberEntity( - _id = 9304, - name = "ADMIN", - email = "admin@example.com", - password = "adminPassword", - role = Role.ADMIN - ) - - val user: MemberEntity = MemberEntity( - _id = 9305, - name = "USER", - email = "user@example.com", - password = "userPassword", - role = Role.MEMBER - ) -} - -object ThemeFixtureV2 { - val createRequest: ThemeCreateRequestV2 = ThemeCreateRequestV2( - name = "Matilda Green", - description = "constituto", - thumbnailUrl = "https://duckduckgo.com/?q=mediocrem", - difficulty = Difficulty.VERY_EASY, - price = 10000, - minParticipants = 3, - maxParticipants = 5, - availableMinutes = 80, - expectedMinutesFrom = 60, - expectedMinutesTo = 70, - isOpen = true - ) -} - -object ScheduleFixture { - val createRequest: ScheduleCreateRequest = ScheduleCreateRequest( - date = LocalDate.now().plusDays(1), - time = LocalTime.now(), - themeId = 1L - ) -}