package roomescape.payment.infrastructure.client; import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.*; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.springframework.test.web.client.match.MockRestRequestMatchers.*; import static org.springframework.test.web.client.response.MockRestResponseCreators.*; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; 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 roomescape.common.exception.ErrorType; import roomescape.common.exception.RoomescapeException; import roomescape.payment.SampleTossPaymentConst; import roomescape.payment.web.PaymentApprove; import roomescape.payment.web.PaymentCancel; @RestClientTest(TossPaymentClient.class) class TossPaymentClientTest { @Autowired private TossPaymentClient tossPaymentClient; @Autowired private MockRestServiceServer mockServer; @Test @DisplayName("결제를 승인한다.") void confirmPayment() { // given mockServer.expect(requestTo("/v1/payments/confirm")) .andExpect(method(HttpMethod.POST)) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(SampleTossPaymentConst.paymentRequestJson)) .andRespond(withStatus(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(SampleTossPaymentConst.confirmJson)); // when PaymentApprove.Request paymentRequest = SampleTossPaymentConst.paymentRequest; PaymentApprove.Response paymentResponse = tossPaymentClient.confirmPayment(paymentRequest); // then assertThat(paymentResponse.paymentKey).isEqualTo(paymentRequest.paymentKey); assertThat(paymentResponse.orderId).isEqualTo(paymentRequest.orderId); } @Test @DisplayName("결제를 취소한다.") void cancelPayment() { // given mockServer.expect(requestTo("/v1/payments/5EnNZRJGvaBX7zk2yd8ydw26XvwXkLrx9POLqKQjmAw4b0e1/cancel")) .andExpect(method(HttpMethod.POST)) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(SampleTossPaymentConst.cancelRequestJson)) .andRespond(withStatus(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON) .body(SampleTossPaymentConst.cancelJson)); // when PaymentCancel.Request cancelRequest = SampleTossPaymentConst.cancelRequest; PaymentCancel.Response paymentCancelResponse = tossPaymentClient.cancelPayment(cancelRequest); // then assertThat(paymentCancelResponse.cancelStatus).isEqualTo("DONE"); assertThat(paymentCancelResponse.cancelReason).isEqualTo(cancelRequest.cancelReason); } @Test @DisplayName("결제 승인 중 400 에러가 발생한다.") void confirmPaymentWithError() { // given mockServer.expect(requestTo("/v1/payments/confirm")) .andExpect(method(HttpMethod.POST)) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(SampleTossPaymentConst.paymentRequestJson)) .andRespond(withStatus(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON) .body(SampleTossPaymentConst.tossPaymentErrorJson)); // when & then assertThatThrownBy(() -> tossPaymentClient.confirmPayment(SampleTossPaymentConst.paymentRequest)) .isInstanceOf(RoomescapeException.class) .hasFieldOrPropertyWithValue("errorType", ErrorType.PAYMENT_ERROR) .hasFieldOrPropertyWithValue("invalidValue", "[ErrorCode = ERROR_CODE, ErrorMessage = Error message]") .hasFieldOrPropertyWithValue("httpStatus", HttpStatus.BAD_REQUEST); } @Test @DisplayName("결제 취소 중 500 에러가 발생한다.") void cancelPaymentWithError() { // given mockServer.expect(requestTo("/v1/payments/5EnNZRJGvaBX7zk2yd8ydw26XvwXkLrx9POLqKQjmAw4b0e1/cancel")) .andExpect(method(HttpMethod.POST)) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(SampleTossPaymentConst.cancelRequestJson)) .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_JSON) .body(SampleTossPaymentConst.tossPaymentErrorJson)); // when & then assertThatThrownBy(() -> tossPaymentClient.cancelPayment(SampleTossPaymentConst.cancelRequest)) .isInstanceOf(RoomescapeException.class) .hasFieldOrPropertyWithValue("errorType", ErrorType.PAYMENT_SERVER_ERROR) .hasFieldOrPropertyWithValue("invalidValue", "[ErrorCode = ERROR_CODE, ErrorMessage = Error message]") .hasFieldOrPropertyWithValue("httpStatus", HttpStatus.INTERNAL_SERVER_ERROR); } }