From eeb288db08348b52047fd96e446be795ba75a342 Mon Sep 17 00:00:00 2001 From: hyeonji91 Date: Wed, 29 Oct 2025 13:13:04 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feature=20#241=20:=20payment=20test=20code?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CustomerOrderService.java | 4 +- .../domain/payment/PaymentControllerTest.java | 78 +++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java diff --git a/src/main/java/com/irum/come2us/domain/order/application/service/CustomerOrderService.java b/src/main/java/com/irum/come2us/domain/order/application/service/CustomerOrderService.java index 3ed39772..1c4c731a 100644 --- a/src/main/java/com/irum/come2us/domain/order/application/service/CustomerOrderService.java +++ b/src/main/java/com/irum/come2us/domain/order/application/service/CustomerOrderService.java @@ -270,8 +270,8 @@ public CustomerOrderResponse prepareOrder(CustomerOrderRequest request) { // 쿠폰 미리 차감 appliedCouponService.createAppliedCouponList(payment, request.couponIdList()); - // 주문 엔티티 생성 PENDING 상태 - String orderNum = "ORD-" + (int) ((Math.random() * 10000000)); + // 주문 엔티티 생성 PENDING 상태 8 자리 랜덤값 + String orderNum = "ORD-" + (int) ((Math.random() * 100000000)); Order order = Order.builder() diff --git a/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java b/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java new file mode 100644 index 00000000..084ef5b2 --- /dev/null +++ b/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java @@ -0,0 +1,78 @@ +package com.irum.come2us.domain.payment; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.irum.come2us.domain.payment.application.service.PaymentService; +import com.irum.come2us.domain.payment.presentation.controller.PaymentController; +import com.irum.come2us.domain.payment.presentation.dto.request.PaymentRequest; +import com.irum.come2us.domain.payment.presentation.dto.response.PaymentResponse; +import com.irum.come2us.global.config.SecurityTestConfig; +import com.irum.come2us.global.config.TestConfig; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.UUID; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = PaymentController.class) +@AutoConfigureMockMvc +@Import({SecurityTestConfig.class, TestConfig.class}) +public class PaymentControllerTest { + + @Autowired + private MockMvc mockMvc; + @MockitoBean + private PaymentService paymentService; + @Autowired + private ObjectMapper objectMapper; + + + @Test + @DisplayName("결제 등록 API") + void paymentCreateApiTest() throws Exception { + UUID orderId = UUID.randomUUID(); + String orderNum = "ORD-777777"; + int totalAmount = 10000; + PaymentRequest request = new PaymentRequest("tossOrderId", "tosspaymentkey", orderId); + PaymentResponse response = new PaymentResponse(orderNum, totalAmount); + + Mockito.when(paymentService.createPayment(request)).thenReturn(response); + + mockMvc.perform(post("/payment") + .with(csrf()) + .with(user("100").roles("CUSTOMER")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.status").value(HttpStatus.OK.value())) + .andExpect(jsonPath("$.data.orderNum").value(orderNum)) + .andExpect(jsonPath("$.data.totalAmount").value(totalAmount)) + .andDo( + document( + "payment-create", + requestFields( + fieldWithPath("tossOrderId").description("토스에서 발급해주는 orderId"), + fieldWithPath("tossPaymentKey").description("토스에서 발급해주는 paymentKey"), + fieldWithPath("orderId").description("결제하려는 주문 id")))); + + } +} From d127184950d4fba1fe0a78131df344770cc3deeb Mon Sep 17 00:00:00 2001 From: hyeonji91 Date: Wed, 29 Oct 2025 14:02:55 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feature=20#241=20:=20restdocs=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + src/docs/asciidoc/_auth.adoc | 1 - src/docs/asciidoc/_payment.adoc | 11 ++++ src/docs/asciidoc/index.adoc | 1 + .../domain/payment/PaymentControllerTest.java | 66 ++++++++++--------- 5 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 src/docs/asciidoc/_payment.adoc diff --git a/build.gradle b/build.gradle index ab9ad451..da34dc16 100644 --- a/build.gradle +++ b/build.gradle @@ -106,6 +106,8 @@ asciidoctor.doFirst { } asciidoctor { + baseDirFollowsSourceFile() // include 기준을 index.adoc 위치로 고정 + sources { include 'index.adoc' } // index.adoc을 진입점으로 attributes('snippets': snippetsDir.get().asFile) configurations 'asciidoctorExt' dependsOn test diff --git a/src/docs/asciidoc/_auth.adoc b/src/docs/asciidoc/_auth.adoc index 77d00074..c2f0e988 100644 --- a/src/docs/asciidoc/_auth.adoc +++ b/src/docs/asciidoc/_auth.adoc @@ -5,7 +5,6 @@ 요청 본문: include::{snippets}/member-login/request-fields.adoc[] - 응답 본문: include::{snippets}/member-login/response-fields.adoc[] diff --git a/src/docs/asciidoc/_payment.adoc b/src/docs/asciidoc/_payment.adoc new file mode 100644 index 00000000..b1f8adc8 --- /dev/null +++ b/src/docs/asciidoc/_payment.adoc @@ -0,0 +1,11 @@ +== 결제 API + +=== 1. 결제 요청 +`POST /payment` + +요청 본문: +include::{snippets}/payment-create/request-fields.adoc[] +응답 본문: +include::{snippets}/payment-create/response-fields.adoc[] +응답: +include::{snippets}/payment-create/http-response.adoc[] \ No newline at end of file diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index c84c9618..be767cb9 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -14,5 +14,6 @@ include::_delivery_address.adoc[] include::_discount.adoc[] include::_deliverypolicy.adoc[] +include::_payment.adoc[] // include::_product.adoc[] diff --git a/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java b/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java index 084ef5b2..28c31aa8 100644 --- a/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java +++ b/src/test/java/com/irum/come2us/domain/payment/PaymentControllerTest.java @@ -1,5 +1,13 @@ package com.irum.come2us.domain.payment; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + import com.fasterxml.jackson.databind.ObjectMapper; import com.irum.come2us.domain.payment.application.service.PaymentService; import com.irum.come2us.domain.payment.presentation.controller.PaymentController; @@ -7,43 +15,27 @@ import com.irum.come2us.domain.payment.presentation.dto.response.PaymentResponse; import com.irum.come2us.global.config.SecurityTestConfig; import com.irum.come2us.global.config.TestConfig; +import java.util.UUID; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; -import java.util.UUID; - -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @WebMvcTest(controllers = PaymentController.class) -@AutoConfigureMockMvc +@AutoConfigureRestDocs @Import({SecurityTestConfig.class, TestConfig.class}) public class PaymentControllerTest { - @Autowired - private MockMvc mockMvc; - @MockitoBean - private PaymentService paymentService; - @Autowired - private ObjectMapper objectMapper; - + @Autowired private MockMvc mockMvc; + @MockitoBean private PaymentService paymentService; + @Autowired private ObjectMapper objectMapper; @Test @DisplayName("결제 등록 API") @@ -56,11 +48,12 @@ void paymentCreateApiTest() throws Exception { Mockito.when(paymentService.createPayment(request)).thenReturn(response); - mockMvc.perform(post("/payment") - .with(csrf()) - .with(user("100").roles("CUSTOMER")) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) + mockMvc.perform( + post("/payment") + .with(csrf()) + .with(user("100").roles("CUSTOMER")) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) .andExpect(status().isOk()) .andExpect(jsonPath("$.success").value(true)) .andExpect(jsonPath("$.status").value(HttpStatus.OK.value())) @@ -70,9 +63,20 @@ void paymentCreateApiTest() throws Exception { document( "payment-create", requestFields( - fieldWithPath("tossOrderId").description("토스에서 발급해주는 orderId"), - fieldWithPath("tossPaymentKey").description("토스에서 발급해주는 paymentKey"), - fieldWithPath("orderId").description("결제하려는 주문 id")))); - + fieldWithPath("tossOrderId") + .description("토스에서 발급해주는 orderId"), + fieldWithPath("tossPaymentKey") + .description("토스에서 발급해주는 paymentKey"), + fieldWithPath("orderId").description("결제하려는 주문 id")), + responseFields( + fieldWithPath("success").description("성공 여부"), + fieldWithPath("status").description("HTTP 상태 코드"), + fieldWithPath("timestamp") + .description("응답 생성 시각 (ISO-8601)"), + subsectionWithPath("data").description("응답 데이터 객체")), + responseFields( + beneathPath("data").withSubsectionId("data"), + fieldWithPath("orderNum").description("주문 번호"), + fieldWithPath("totalAmount").description("실 결제 금액")))); } }