Skip to content

Commit db5d877

Browse files
authored
Merge pull request #206 from prgrms-web-devcourse-final-project/fix#198
[Fix]: 테스트 코드 수정
2 parents c7bcd0e + df2476f commit db5d877

File tree

8 files changed

+256
-113
lines changed

8 files changed

+256
-113
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencies {
7070
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
7171
testImplementation("com.github.codemonstur:embedded-redis:1.4.2")
7272
implementation("net.datafaker:datafaker:2.1.0")
73+
testImplementation("org.springframework.cloud:spring-cloud-contract-wiremock:4.1.4")
7374
}
7475

7576
tasks.withType<Test> {

src/main/java/com/backend/domain/payment/controller/ApiV1PaymentController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public RsData<TossIssueBillingKeyResponse> issueBillingKey(
9292

9393
return RsData.ok("빌링키가 발급되었습니다.", data);
9494
}
95+
9596
@GetMapping("/toss/billing-auth-params")
9697
@Operation(
9798
summary = "토스 카드등록(빌링) 팝업 파라미터 조회",

src/test/java/com/backend/domain/cash/controller/ApiV1CashControllerTest.java

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ void setUp() {
8888
mvc.perform(get("/api/v1/cash"))
8989
.andDo(print())
9090
.andExpect(status().isOk())
91-
.andExpect(jsonPath("$.memberId", is(me.getId().intValue())))
92-
.andExpect(jsonPath("$.cashId", is(myCash.getId().intValue())))
93-
.andExpect(jsonPath("$.balance", is(10_000)))
94-
.andExpect(jsonPath("$.createDate", notNullValue()))
95-
.andExpect(jsonPath("$.modifyDate", notNullValue()));
91+
.andExpect(jsonPath("$.data.memberId", is(me.getId().intValue())))
92+
.andExpect(jsonPath("$.data.cashId", is(myCash.getId().intValue())))
93+
.andExpect(jsonPath("$.data.balance", is(10_000)))
94+
.andExpect(jsonPath("$.data.createDate", notNullValue()))
95+
.andExpect(jsonPath("$.data.modifyDate", notNullValue()));
9696
}
9797

9898
@Test
@@ -113,23 +113,23 @@ void setUp() {
113113
.param("size", "20"))
114114
.andDo(print())
115115
.andExpect(status().isOk())
116-
.andExpect(jsonPath("$.page", is(1)))
117-
.andExpect(jsonPath("$.size", is(20)))
118-
.andExpect(jsonPath("$.total", is(2)))
119-
.andExpect(jsonPath("$.items", hasSize(2)))
116+
.andExpect(jsonPath("$.data.page", is(1)))
117+
.andExpect(jsonPath("$.data.size", is(20)))
118+
.andExpect(jsonPath("$.data.total", is(2)))
119+
.andExpect(jsonPath("$.data.items", hasSize(2)))
120120
// 최신(id DESC) → 출금(7000) 먼저
121-
.andExpect(jsonPath("$.items[0].type", is("WITHDRAW")))
122-
.andExpect(jsonPath("$.items[0].amount", is(3_000)))
123-
.andExpect(jsonPath("$.items[0].balanceAfter", is(7_000)))
124-
.andExpect(jsonPath("$.items[0].related.type", is("PAYMENT")))
125-
.andExpect(jsonPath("$.items[0].related.id", is(102)))
121+
.andExpect(jsonPath("$.data.items[0].type", is("WITHDRAW")))
122+
.andExpect(jsonPath("$.data.items[0].amount", is(3_000)))
123+
.andExpect(jsonPath("$.data.items[0].balanceAfter", is(7_000)))
124+
.andExpect(jsonPath("$.data.items[0].related.type", is("PAYMENT")))
125+
.andExpect(jsonPath("$.data.items[0].related.id", is(102)))
126126

127127
// 그 다음 입금(10000)
128-
.andExpect(jsonPath("$.items[1].type", is("DEPOSIT")))
129-
.andExpect(jsonPath("$.items[1].amount", is(10_000)))
130-
.andExpect(jsonPath("$.items[1].balanceAfter", is(10_000)))
131-
.andExpect(jsonPath("$.items[1].related.type", is("PAYMENT")))
132-
.andExpect(jsonPath("$.items[1].related.id", is(101)));
128+
.andExpect(jsonPath("$.data.items[1].type", is("DEPOSIT")))
129+
.andExpect(jsonPath("$.data.items[1].amount", is(10_000)))
130+
.andExpect(jsonPath("$.data.items[1].balanceAfter", is(10_000)))
131+
.andExpect(jsonPath("$.data.items[1].related.type", is("PAYMENT")))
132+
.andExpect(jsonPath("$.data.items[1].related.id", is(101)));
133133
}
134134

135135
@Test
@@ -146,16 +146,16 @@ void setUp() {
146146
mvc.perform(get("/api/v1/cash/transactions/{id}", txWithdraw.getId()))
147147
.andDo(print())
148148
.andExpect(status().isOk())
149-
.andExpect(jsonPath("$.transactionId", is(txWithdraw.getId().intValue())))
150-
.andExpect(jsonPath("$.cashId", is(myCash.getId().intValue())))
151-
.andExpect(jsonPath("$.type", is("WITHDRAW")))
152-
.andExpect(jsonPath("$.amount", is(3_000)))
153-
.andExpect(jsonPath("$.balanceAfter", is(7_000)))
154-
.andExpect(jsonPath("$.createdAt", notNullValue()))
149+
.andExpect(jsonPath("$.data.transactionId", is(txWithdraw.getId().intValue())))
150+
.andExpect(jsonPath("$.data.cashId", is(myCash.getId().intValue())))
151+
.andExpect(jsonPath("$.data.type", is("WITHDRAW")))
152+
.andExpect(jsonPath("$.data.amount", is(3_000)))
153+
.andExpect(jsonPath("$.data.balanceAfter", is(7_000)))
154+
.andExpect(jsonPath("$.data.createdAt", notNullValue()))
155155
// Related + Links (PAYMENT면 paymentDetail 링크 생성)
156-
.andExpect(jsonPath("$.related.type", is("PAYMENT")))
157-
.andExpect(jsonPath("$.related.id", is(102)))
158-
.andExpect(jsonPath("$.related.links.paymentDetail", is("/api/v1/payments/me/102")));
156+
.andExpect(jsonPath("$.data.related.type", is("PAYMENT")))
157+
.andExpect(jsonPath("$.data.related.id", is(102)))
158+
.andExpect(jsonPath("$.data.related.links.paymentDetail", is("/api/v1/payments/me/102")));
159159
}
160160

161161
@Test

src/test/java/com/backend/domain/cash/service/CashServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class CashServiceTest {
7171
// 검증: 잔액 2_000, WITHDRAW, 금액 8_000, 관련 타입 BID
7272
assertThat(cash.getBalance()).isEqualTo(2_000L);
7373
assertThat(tx.getType()).isEqualTo(CashTxType.WITHDRAW);
74-
assertThat(tx.getAmount()).isEqualTo(8_000L);
74+
assertThat(tx.getAmount()).isEqualTo(-8_000L);
7575
assertThat(tx.getBalanceAfter()).isEqualTo(2_000L);
7676
assertThat(tx.getRelatedType()).isEqualTo(RelatedType.BID);
7777
assertThat(tx.getRelatedId()).isEqualTo(123L);

src/test/java/com/backend/domain/payment/controller/ApiV1PaymentControllerTest.java

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.backend.domain.payment.repository.PaymentMethodRepository;
1111
import com.backend.domain.payment.repository.PaymentRepository;
1212
import com.backend.domain.payment.service.TossBillingClientService;
13+
import com.backend.global.security.JwtUtil;
1314
import com.fasterxml.jackson.databind.ObjectMapper;
1415
import org.junit.jupiter.api.BeforeEach;
1516
import org.junit.jupiter.api.Test;
@@ -21,12 +22,12 @@
2122
import org.springframework.test.context.bean.override.mockito.MockitoBean;
2223
import org.springframework.test.web.servlet.MockMvc;
2324
import org.springframework.transaction.annotation.Transactional;
24-
import static org.hamcrest.Matchers.is;
2525
import static org.hamcrest.Matchers.notNullValue;
2626
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
27+
import static org.junit.jupiter.api.Assertions.assertTrue;
2728
import static org.mockito.ArgumentMatchers.*;
2829
import static org.mockito.BDDMockito.given;
29-
30+
import static org.hamcrest.Matchers.*;
3031
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
3132
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
3233
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@@ -42,7 +43,11 @@ class ApiV1PaymentControllerTest {
4243
@Autowired MemberRepository memberRepository;
4344
@Autowired PaymentMethodRepository paymentMethodRepository;
4445
@Autowired PaymentRepository paymentRepository;
45-
46+
@Autowired
47+
JwtUtil jwtUtil;
48+
private String bearer(String email) {
49+
return "Bearer " + jwtUtil.generateAccessToken(email);
50+
}
4651
// 외부 호출은 Mock 처리 (실제 네트워크 X)
4752
@MockitoBean
4853
TossBillingClientService tossBillingClientService;
@@ -104,20 +109,20 @@ void charge_success() throws Exception {
104109
mockMvc.perform(post("/api/v1/payments")
105110
.contentType(MediaType.APPLICATION_JSON)
106111
.content(om.writeValueAsString(req)))
107-
.andExpect(status().isOk())
112+
.andExpect(status().isCreated())
108113
// PaymentResponse(JSON) 필드 검증
109-
.andExpect(jsonPath("$.paymentId", notNullValue()))
110-
.andExpect(jsonPath("$.paymentMethodId", is(pmCard.getId().intValue())))
111-
.andExpect(jsonPath("$.status", is("SUCCESS")))
112-
.andExpect(jsonPath("$.amount", is(5_000)))
113-
.andExpect(jsonPath("$.currency", is("KRW")))
114-
.andExpect(jsonPath("$.provider", is("toss")))
115-
.andExpect(jsonPath("$.methodType", is("CARD")))
116-
.andExpect(jsonPath("$.transactionId", is("payKey_abc123")))
117-
.andExpect(jsonPath("$.createdAt", notNullValue()))
118-
.andExpect(jsonPath("$.paidAt", notNullValue()))
119-
.andExpect(jsonPath("$.idempotencyKey", is("idem-001")))
120-
.andExpect(jsonPath("$.balanceAfter", notNullValue()));
114+
.andExpect(jsonPath("$.data.paymentId", notNullValue()))
115+
.andExpect(jsonPath("$.data.paymentMethodId", is(pmCard.getId().intValue())))
116+
.andExpect(jsonPath("$.data.status", is("SUCCESS")))
117+
.andExpect(jsonPath("$.data.amount", is(5_000)))
118+
.andExpect(jsonPath("$.data.currency", is("KRW")))
119+
.andExpect(jsonPath("$.data.provider", is("toss")))
120+
.andExpect(jsonPath("$.data.methodType", is("CARD")))
121+
.andExpect(jsonPath("$.data.transactionId", is("payKey_abc123")))
122+
.andExpect(jsonPath("$.data.createdAt", notNullValue()))
123+
.andExpect(jsonPath("$.data.paidAt", notNullValue()))
124+
.andExpect(jsonPath("$.data.idempotencyKey", is("idem-001")))
125+
.andExpect(jsonPath("$.data.balanceAfter", notNullValue()));
121126
}
122127

123128
// 2) 멱등: 같은 키로 두 번 쏘면 같은 결과
@@ -140,17 +145,17 @@ void charge_idempotent_returns_same_result() throws Exception {
140145
mockMvc.perform(post("/api/v1/payments")
141146
.contentType(MediaType.APPLICATION_JSON)
142147
.content(om.writeValueAsString(req)))
143-
.andExpect(status().isOk())
144-
.andExpect(jsonPath("$.status", is("SUCCESS")))
145-
.andExpect(jsonPath("$.transactionId", is("payKey_idem")));
148+
.andExpect(status().isCreated())
149+
.andExpect(jsonPath("$.data.status", is("SUCCESS")))
150+
.andExpect(jsonPath("$.data.transactionId", is("payKey_idem")));
146151

147152
// 2차 호출(같은 키) → PG 안 타고 기존 결과 그대로
148153
mockMvc.perform(post("/api/v1/payments")
149154
.contentType(MediaType.APPLICATION_JSON)
150155
.content(om.writeValueAsString(req)))
151-
.andExpect(status().isOk())
152-
.andExpect(jsonPath("$.status", is("SUCCESS")))
153-
.andExpect(jsonPath("$.transactionId", is("payKey_idem")));
156+
.andExpect(status().isCreated())
157+
.andExpect(jsonPath("$.data.status", is("SUCCESS")))
158+
.andExpect(jsonPath("$.data.transactionId", is("payKey_idem")));
154159
}
155160

156161
// 3) 내 결제 목록 조회
@@ -169,18 +174,18 @@ void get_my_payments_list() throws Exception {
169174
mockMvc.perform(post("/api/v1/payments")
170175
.contentType(MediaType.APPLICATION_JSON)
171176
.content(om.writeValueAsString(req)))
172-
.andExpect(status().isOk());
177+
.andExpect(status().isCreated());
173178

174179
mockMvc.perform(get("/api/v1/payments/me")
175180
.param("page", "1")
176181
.param("size", "20"))
177182
.andExpect(status().isOk())
178-
.andExpect(jsonPath("$.page", is(1)))
179-
.andExpect(jsonPath("$.size", is(20)))
180-
.andExpect(jsonPath("$.total", greaterThanOrEqualTo(1)))
181-
.andExpect(jsonPath("$.items[0].paymentId", notNullValue()))
182-
.andExpect(jsonPath("$.items[0].amount", notNullValue()))
183-
.andExpect(jsonPath("$.items[0].status", notNullValue()));
183+
.andExpect(jsonPath("$.data.page", is(1)))
184+
.andExpect(jsonPath("$.data.size", is(20)))
185+
.andExpect(jsonPath("$.data.total", greaterThanOrEqualTo(1)))
186+
.andExpect(jsonPath("$.data.items[0].paymentId", notNullValue()))
187+
.andExpect(jsonPath("$.data.items[0].amount", notNullValue()))
188+
.andExpect(jsonPath("$.data.items[0].status", notNullValue()));
184189
}
185190

186191
// 4) 내 결제 단건 상세
@@ -200,31 +205,33 @@ void get_my_payment_detail() throws Exception {
200205
String body = mockMvc.perform(post("/api/v1/payments")
201206
.contentType(MediaType.APPLICATION_JSON)
202207
.content(om.writeValueAsString(req)))
203-
.andExpect(status().isOk())
208+
.andExpect(status().isCreated())
204209
.andReturn().getResponse().getContentAsString();
205210

211+
var root = om.readTree(body);
206212
// JsonPath로 꺼내도 되고, 간단히 Jackson으로 map 해도 됨
207-
long paymentId = om.readTree(body).get("paymentId").asLong();
213+
long paymentId = root.path("data").path("paymentId").asLong(root.path("paymentId").asLong(0));
214+
assertTrue(paymentId > 0, "paymentId must be positive");
208215

209216
mockMvc.perform(get("/api/v1/payments/me/{paymentId}", paymentId))
210217
.andExpect(status().isOk())
211-
.andExpect(jsonPath("$.paymentId", is((int) paymentId)))
212-
.andExpect(jsonPath("$.amount", is(4_000)))
213-
.andExpect(jsonPath("$.status", is("SUCCESS")))
214-
.andExpect(jsonPath("$.transactionId", is("k2")))
215-
.andExpect(jsonPath("$.paidAt", notNullValue()));
218+
.andExpect(jsonPath("$.data.paymentId", is((int) paymentId)))
219+
.andExpect(jsonPath("$.data.amount", is(4_000)))
220+
.andExpect(jsonPath("$.data.status", is("SUCCESS")))
221+
.andExpect(jsonPath("$.data.transactionId", is("k2")))
222+
.andExpect(jsonPath("$.data.paidAt", notNullValue()));
216223
}
217224

218225
// 5) 토스 빌링키 발급 API
219226
@Test
220227
@WithMockUser(username = "[email protected]")
221228
void issue_billing_key_success() throws Exception {
222-
given(tossBillingClientService.issueBillingKey(startsWith("user-"), eq("AUTH-123")))
229+
given(tossBillingClientService.issueBillingKey(org.mockito.ArgumentMatchers.startsWith("user-"), eq("AUTH-123")))
223230
.willReturn(TossIssueBillingKeyResponse.builder()
224231
.billingKey("BILL-XYZ")
225232
.provider("toss")
226233
.cardBrand("SHINHAN")
227-
.cardNumber("****-****-****-1234")
234+
.last4("****-****-****-1234")
228235
.expMonth(12)
229236
.expYear(2030)
230237
.build());
@@ -237,9 +244,9 @@ void issue_billing_key_success() throws Exception {
237244
.contentType(MediaType.APPLICATION_JSON)
238245
.content(payload))
239246
.andExpect(status().isOk())
240-
.andExpect(jsonPath("$.billingKey", is("BILL-XYZ")))
241-
.andExpect(jsonPath("$.provider", is("toss")))
242-
.andExpect(jsonPath("$.cardBrand", is("SHINHAN")));
247+
.andExpect(jsonPath("$.data.billingKey", is("BILL-XYZ")))
248+
.andExpect(jsonPath("$.data.provider", is("toss")))
249+
.andExpect(jsonPath("$.data.cardBrand", is("SHINHAN")));
243250
}
244251

245252
// 6) 인증 없으면 401
@@ -255,4 +262,30 @@ void charge_unauthorized_401() throws Exception {
255262
.content(om.writeValueAsString(req)))
256263
.andExpect(status().isUnauthorized());
257264
}
265+
266+
// 토스 카드등록(빌링) 팝업 파라미터 조회
267+
@Test
268+
@WithMockUser(username = "[email protected]")
269+
void get_billing_auth_params_success() throws Exception {
270+
// setUp()에서 me 저장되어 있음: customerKey = "user-" + me.getId()
271+
String expectedCustomerKey = "user-" + me.getId();
272+
273+
mockMvc.perform(get("/api/v1/payments/toss/billing-auth-params"))
274+
.andExpect(status().isOk())
275+
.andExpect(jsonPath("$.data.clientKey", notNullValue())) // 값만 존재 검증 (테스트 환경 clientKey 미설정 대비)
276+
.andExpect(jsonPath("$.data.customerKey", is(expectedCustomerKey))) // user-{id}
277+
.andExpect(jsonPath("$.data.successUrl", containsString("/payments/toss/billing-success.html")))
278+
.andExpect(jsonPath("$.data.failUrl", containsString("/payments/toss/billing-fail.html")));
279+
}
280+
281+
// 멱등키 발급
282+
@Test
283+
void new_idempotency_key_success() throws Exception {
284+
mockMvc.perform(get("/api/v1/payments/idempotency-key")
285+
.header("Authorization", bearer("[email protected]")))
286+
.andExpect(status().isOk())
287+
.andExpect(jsonPath("$.data.idempotencyKey", notNullValue()))
288+
// 간단한 UUID 패턴(36자 16진/하이픈) 체크
289+
.andExpect(jsonPath("$.data.idempotencyKey", matchesPattern("^[0-9a-fA-F\\-]{36}$")));
290+
}
258291
}

0 commit comments

Comments
 (0)