pricelees 9f8ee8cc02 [#18] 코드 정리 및 일부 컨벤션 통일 (#19)
<!-- 제목 양식 -->
<!-- [이슈번호] 작업 요약 (예시: [#10] Gitea 템플릿 생성) -->

## 📝 관련 이슈 및 PR

**PR과 관련된 이슈 번호**
- #18

##  작업 내용
<!-- 어떤 작업을 했는지 알려주세요! -->
- 기존 자바와의 호환성을 위해 사용하던 \@Jvm.. 어노테이션 및 팩토리 메서드 제거
- 기존에 get, find, save 등으로 산재되어 있던 메서드 컨벤션 통일
- 일부 API endpoint 수정
- 테이블 이름 단수 -> 복수 수정

추가적으로 개선이 필요한 점은 있지만, 이는 기능 개선 과정에서 수정할 예정

## 🧪 테스트
<!-- 어떤 테스트를 생각했고 진행했는지 알려주세요! -->
각 작업 마다 전체 테스트 수행 및 정상 동작 확인

## 📚 참고 자료 및 기타
<!-- 참고한 자료, 또는 논의할 사항이 있다면 알려주세요! -->

Reviewed-on: #19
Co-authored-by: pricelees <priceelees@gmail.com>
Co-committed-by: pricelees <priceelees@gmail.com>
2025-07-22 09:05:31 +00:00

139 lines
5.6 KiB
Kotlin

package roomescape.payment.infrastructure.client
import io.kotest.assertions.assertSoftly
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.ResponseActions
import org.springframework.test.web.client.match.MockRestRequestMatchers.*
import org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
import org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess
import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException
import roomescape.payment.web.PaymentCancelRequest
import roomescape.payment.web.PaymentCancelResponse
@RestClientTest(TossPaymentClient::class)
class TossPaymentClientTest(
@Autowired val client: TossPaymentClient,
@Autowired val mockServer: MockRestServiceServer
) : FunSpec() {
init {
context("결제 승인 요청") {
fun commonAction(): ResponseActions = mockServer.expect {
requestTo("/v1/payments/confirm")
}.andExpect {
method(HttpMethod.POST)
}.andExpect {
content().contentType(MediaType.APPLICATION_JSON)
}.andExpect {
content().json(SampleTossPaymentConst.paymentRequestJson)
}
test("성공 응답") {
commonAction().andRespond {
withSuccess()
.contentType(MediaType.APPLICATION_JSON)
.body(SampleTossPaymentConst.confirmJson)
.createResponse(it)
}
// when
val paymentRequest = SampleTossPaymentConst.paymentRequest
val paymentResponse: PaymentApproveResponse = client.confirm(paymentRequest)
assertSoftly(paymentResponse) {
this.paymentKey shouldBe paymentRequest.paymentKey
this.orderId shouldBe paymentRequest.orderId
this.totalAmount shouldBe paymentRequest.amount
}
}
test("400 에러 발생") {
commonAction().andRespond {
withStatus(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(SampleTossPaymentConst.tossPaymentErrorJson)
.createResponse(it)
}
// when
val paymentRequest = SampleTossPaymentConst.paymentRequest
// then
val exception = shouldThrow<RoomescapeException> {
client.confirm(paymentRequest)
}
assertSoftly(exception) {
this.errorType shouldBe ErrorType.PAYMENT_ERROR
this.invalidValue shouldBe "[ErrorCode = ERROR_CODE, ErrorMessage = Error message]"
this.httpStatus shouldBe HttpStatus.BAD_REQUEST
}
}
}
context("결제 취소 요청") {
fun commonAction(): ResponseActions = mockServer.expect {
requestTo("/v1/payments/${SampleTossPaymentConst.paymentKey}/cancel")
}.andExpect {
method(HttpMethod.POST)
}.andExpect {
content().contentType(MediaType.APPLICATION_JSON)
}.andExpect {
content().json(SampleTossPaymentConst.cancelRequestJson)
}
test("성공 응답") {
commonAction().andRespond {
withSuccess()
.contentType(MediaType.APPLICATION_JSON)
.body(SampleTossPaymentConst.cancelJson)
.createResponse(it)
}
// when
val cancelRequest: PaymentCancelRequest = SampleTossPaymentConst.cancelRequest
val cancelResponse: PaymentCancelResponse = client.cancel(cancelRequest)
assertSoftly(cancelResponse) {
this.cancelStatus shouldBe "DONE"
this.cancelReason shouldBe cancelRequest.cancelReason
this.cancelAmount shouldBe cancelRequest.amount
}
}
test("500 에러 발생") {
commonAction().andRespond {
withStatus(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
.body(SampleTossPaymentConst.tossPaymentErrorJson)
.createResponse(it)
}
// when
val cancelRequest: PaymentCancelRequest = SampleTossPaymentConst.cancelRequest
// then
val exception = shouldThrow<RoomescapeException> {
client.cancel(cancelRequest)
}
assertSoftly(exception) {
this.errorType shouldBe ErrorType.PAYMENT_SERVER_ERROR
this.invalidValue shouldBe "[ErrorCode = ERROR_CODE, ErrorMessage = Error message]"
this.httpStatus shouldBe HttpStatus.INTERNAL_SERVER_ERROR
}
}
}
}
}