카드 매입 승인 경로 Spring Boot 3 전환 (ACX-E2E-1785394564819)
This commit is contained in:
parent
9536892e5a
commit
3790d30330
1 changed files with 242 additions and 0 deletions
242
src/test/java/com/acquirex/approval/ApprovalTests.java
Normal file
242
src/test/java/com/acquirex/approval/ApprovalTests.java
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
package com.acquirex.approval;
|
||||||
|
|
||||||
|
import com.acquirex.approval.domain.ApprovalStatus;
|
||||||
|
import com.acquirex.approval.dto.ApprovalRequest;
|
||||||
|
import com.acquirex.approval.dto.ApprovalResponse;
|
||||||
|
import com.acquirex.approval.service.CardAcquisitionApprovalService;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CardAcquisitionApprovalService and Controller.
|
||||||
|
* Tests Spring Boot 3 migrated approval logic with Jakarta validation.
|
||||||
|
*/
|
||||||
|
@WebMvcTest
|
||||||
|
@DisplayName("Card Acquisition Approval Tests")
|
||||||
|
@TestMethodOrder(MethodOrderer.DisplayName.class)
|
||||||
|
class ApprovalTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private CardAcquisitionApprovalService approvalService;
|
||||||
|
|
||||||
|
// ========== Service Unit Tests ==========
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Service: processApproval")
|
||||||
|
class ServiceProcessApprovalTests {
|
||||||
|
|
||||||
|
private CardAcquisitionApprovalService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
service = new CardAcquisitionApprovalService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("01 - should approve transaction below threshold")
|
||||||
|
void shouldApproveTransactionBelowThreshold() {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-001", "4111111111111111",
|
||||||
|
"MERCHANT-001", new BigDecimal("100.00"));
|
||||||
|
ApprovalResponse response = service.processApproval(request);
|
||||||
|
assertEquals(ApprovalStatus.APPROVED, response.getStatus());
|
||||||
|
assertEquals("REQ-001", response.getRequestId());
|
||||||
|
assertNotNull(response.getProcessedAt());
|
||||||
|
assertTrue(response.getMessage().contains("approved"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("02 - should pend transaction above high risk threshold")
|
||||||
|
void shouldPendTransactionAboveHighRiskThreshold() {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-002", "4111111111111111",
|
||||||
|
"MERCHANT-002", new BigDecimal("600000.00"));
|
||||||
|
ApprovalResponse response = service.processApproval(request);
|
||||||
|
assertEquals(ApprovalStatus.PENDING, response.getStatus());
|
||||||
|
assertTrue(response.getMessage().contains("pending"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("03 - should reject transaction above max amount")
|
||||||
|
void shouldRejectTransactionAboveMaxAmount() {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-003", "4111111111111111",
|
||||||
|
"MERCHANT-003", new BigDecimal("1500000.00"));
|
||||||
|
ApprovalResponse response = service.processApproval(request);
|
||||||
|
assertEquals(ApprovalStatus.REJECTED, response.getStatus());
|
||||||
|
assertTrue(response.getMessage().contains("rejected"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Service: validateRequest")
|
||||||
|
class ServiceValidateRequestTests {
|
||||||
|
|
||||||
|
private CardAcquisitionApprovalService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
service = new CardAcquisitionApprovalService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("04 - should throw exception for invalid card number")
|
||||||
|
void shouldThrowExceptionForInvalidCardNumber() {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-004", "123",
|
||||||
|
"MERCHANT-001", new BigDecimal("100.00"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> service.validateRequest(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("05 - should throw exception for blank merchant ID")
|
||||||
|
void shouldThrowExceptionForBlankMerchantId() {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-005", "4111111111111111",
|
||||||
|
" ", new BigDecimal("100.00"));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> service.validateRequest(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Service: determineApprovalStatus")
|
||||||
|
class ServiceDetermineStatusTests {
|
||||||
|
|
||||||
|
private CardAcquisitionApprovalService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
service = new CardAcquisitionApprovalService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("06 - should return APPROVED for amount below threshold")
|
||||||
|
void shouldReturnApprovedForLowAmount() {
|
||||||
|
assertEquals(ApprovalStatus.APPROVED, service.determineApprovalStatus(new BigDecimal("100.00")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("07 - should return PENDING for high risk amount")
|
||||||
|
void shouldReturnPendingForHighRiskAmount() {
|
||||||
|
assertEquals(ApprovalStatus.PENDING, service.determineApprovalStatus(new BigDecimal("500001.00")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("08 - should return REJECTED for amount exceeding max")
|
||||||
|
void shouldReturnRejectedForExceedingMax() {
|
||||||
|
assertEquals(ApprovalStatus.REJECTED, service.determineApprovalStatus(new BigDecimal("1000001.00")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Service: maskCardNumber")
|
||||||
|
class ServiceMaskCardNumberTests {
|
||||||
|
|
||||||
|
private CardAcquisitionApprovalService service;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
service = new CardAcquisitionApprovalService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("09 - should mask card number correctly")
|
||||||
|
void shouldMaskCardNumberCorrectly() {
|
||||||
|
assertEquals("****-****-****-1111", service.maskCardNumber("4111111111111111"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("10 - should return default mask for short card number")
|
||||||
|
void shouldReturnDefaultMaskForShortNumber() {
|
||||||
|
assertEquals("****", service.maskCardNumber("123"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("11 - should return default mask for null card number")
|
||||||
|
void shouldReturnDefaultMaskForNull() {
|
||||||
|
assertEquals("****", service.maskCardNumber(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== Controller Integration Tests ==========
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("Controller: POST /api/v1/approvals")
|
||||||
|
class ControllerTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("12 - should return 200 for approved transaction")
|
||||||
|
void shouldReturn200ForApprovedTransaction() throws Exception {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-001", "4111111111111111",
|
||||||
|
"MERCHANT-001", new BigDecimal("100.00"));
|
||||||
|
ApprovalResponse response = new ApprovalResponse(1L, "REQ-001", ApprovalStatus.APPROVED,
|
||||||
|
new BigDecimal("100.00"), LocalDateTime.now(), "Card acquisition approved successfully");
|
||||||
|
when(approvalService.processApproval(any(ApprovalRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
mockMvc.perform(post("/api/v1/approvals")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(request)))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.requestId").value("REQ-001"))
|
||||||
|
.andExpect(jsonPath("$.status").value("APPROVED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("13 - should return 400 for validation error")
|
||||||
|
void shouldReturn400ForValidationError() throws Exception {
|
||||||
|
String invalidRequest = "{\"cardNumber\":\"\",\"merchantId\":\"\"}";
|
||||||
|
mockMvc.perform(post("/api/v1/approvals")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(invalidRequest))
|
||||||
|
.andExpect(status().isBadRequest())
|
||||||
|
.andExpect(jsonPath("$.error").value("Validation Failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("14 - should return 400 for rejected transaction")
|
||||||
|
void shouldReturn400ForRejectedTransaction() throws Exception {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-002", "4111111111111111",
|
||||||
|
"MERCHANT-002", new BigDecimal("2000000.00"));
|
||||||
|
ApprovalResponse response = new ApprovalResponse(2L, "REQ-002", ApprovalStatus.REJECTED,
|
||||||
|
new BigDecimal("2000000.00"), LocalDateTime.now(), "Card acquisition rejected");
|
||||||
|
when(approvalService.processApproval(any(ApprovalRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
mockMvc.perform(post("/api/v1/approvals")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(request)))
|
||||||
|
.andExpect(status().isBadRequest())
|
||||||
|
.andExpect(jsonPath("$.status").value("REJECTED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("15 - should return 202 for pending transaction")
|
||||||
|
void shouldReturn202ForPendingTransaction() throws Exception {
|
||||||
|
ApprovalRequest request = new ApprovalRequest("REQ-003", "4111111111111111",
|
||||||
|
"MERCHANT-003", new BigDecimal("600000.00"));
|
||||||
|
ApprovalResponse response = new ApprovalResponse(3L, "REQ-003", ApprovalStatus.PENDING,
|
||||||
|
new BigDecimal("600000.00"), LocalDateTime.now(), "Card acquisition pending manual review");
|
||||||
|
when(approvalService.processApproval(any(ApprovalRequest.class))).thenReturn(response);
|
||||||
|
|
||||||
|
mockMvc.perform(post("/api/v1/approvals")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.content(objectMapper.writeValueAsString(request)))
|
||||||
|
.andExpect(status().isAccepted())
|
||||||
|
.andExpect(jsonPath("$.status").value("PENDING"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue