2d17387def
- standard-layout-djb.csv: EZDATA size 1→0 변경 FlatReader가 refPath/refValue 조건(HEAD.corp_tlwn_virt_brcd=ERP)을 평가하여 비ERP 파싱 시 EZDATA 블록을 자동으로 size=0 유지 → 직렬화 제외 - StandardMessageEzdataJsonFlowTest: 비ERP 검증 강화 ERP 전용 필드 빈값 검증 → size=0 확인 + JSON 직렬화 제외 직접 검증으로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
423 lines
16 KiB
Java
423 lines
16 KiB
Java
package com.eactive.eai.custom.message;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.TestInstance;
|
|
import org.mockito.Mockito;
|
|
import org.mockito.invocation.InvocationOnMock;
|
|
import org.mockito.stubbing.Answer;
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
import com.eactive.eai.common.monitor.EAIServiceMonitor;
|
|
import com.eactive.eai.common.property.PropManager;
|
|
import com.eactive.eai.common.server.EAIServerManager;
|
|
import com.eactive.eai.common.util.ApplicationContextProvider;
|
|
import com.eactive.eai.message.StandardItem;
|
|
import com.eactive.eai.message.StandardMessage;
|
|
import com.eactive.eai.message.manager.StandardMessageManager;
|
|
import com.eactive.eai.message.parser.JsonReader;
|
|
import com.eactive.eai.message.service.InterfaceMapper;
|
|
import com.eactive.eai.common.message.MessageType;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
|
|
/**
|
|
* DJBank 표준전문 EZDATA(전자금융공통영역) JSON 처리 흐름 통합 테스트
|
|
*
|
|
* 검증 시나리오:
|
|
* 1. EZDATA 포함 요청 JSON 파싱 — corp_tlwn_virt_brcd=ERP 조건 활성
|
|
* 2. EZDATA 핵심 필드 값 검증
|
|
* 3. EZDATA 조건 미충족(비ERP) 시 JSON 직렬화 제외 검증
|
|
* 4. EZDATA 포함 JSON 왕복(parse → serialize) 일관성
|
|
* 5. coordinateAfterCreateMessageByRule 후 EZDATA 보존
|
|
* 6. coordinateBeforeResponse 후 EZDATA 포함 직렬화
|
|
* 7. 오류 응답 생성 시 EZDATA 보존
|
|
*/
|
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
|
class StandardMessageEzdataJsonFlowTest {
|
|
|
|
private static final String TEST_GUID =
|
|
"20260420" + "120000" + "000" + "EAI" + "01" + "123456789012" + "000001";
|
|
|
|
private static final String TEST_IF_ID = "IF_DJBTEST_EZ001";
|
|
private static final String TEST_TX_ID = "TXTEST000002";
|
|
|
|
/**
|
|
* ERP 채널 요청 JSON — corp_tlwn_virt_brcd=ERP → EZDATA 블록 활성화
|
|
*/
|
|
private static final String ERP_REQ_JSON =
|
|
"{"
|
|
+ "\"HEAD\":{"
|
|
+ "\"nxgn_stnd_idfr\":\"JERA\","
|
|
+ "\"guid\":\"" + TEST_GUID + "\","
|
|
+ "\"guid_prgs_no\":\"1\","
|
|
+ "\"stnd_mesg_ver\":\"R10\","
|
|
+ "\"ortr_guid\":\"" + TEST_GUID + "\","
|
|
+ "\"dman_rspn_dvcd\":\"S\","
|
|
+ "\"if_id\":\"" + TEST_IF_ID + "\","
|
|
+ "\"procs_rslt_dvcd\":\"S\","
|
|
+ "\"tx_id\":\"" + TEST_TX_ID + "\","
|
|
+ "\"chnl_tycd\":\"EAI\","
|
|
+ "\"hmab_dvcd\":\"1\","
|
|
+ "\"corp_tlwn_virt_brcd\":\"ERP\","
|
|
+ "\"trnm_sys_dvcd\":\"OPA\","
|
|
+ "\"frst_trnm_sys_dvcd\":\"OPA\","
|
|
+ "\"sys_env_dvcd\":\"D\","
|
|
+ "\"frst_mesg_dman_dt\":\"20260420\","
|
|
+ "\"frst_mesg_dman_time\":\"120000000\""
|
|
+ "},"
|
|
+ "\"EZDATA\":{"
|
|
+ "\"login_mhod_dvcd\":\"1\","
|
|
+ "\"elfn_bnkn_dvcd\":\"01\","
|
|
+ "\"usr_no\":\"USR0000000000001\","
|
|
+ "\"rgsr_id\":\"REG_ID_000000001\","
|
|
+ "\"secu_media_dvcd\":\"00\","
|
|
+ "\"secu_media_sta_dvcd\":\"00\","
|
|
+ "\"brll_srcd_yn\":\"N\","
|
|
+ "\"next_data_exis_yn\":\"N\","
|
|
+ "\"page_no\":\"00001\","
|
|
+ "\"page_size\":\"00020\","
|
|
+ "\"dup_tx_yn\":\"N\""
|
|
+ "},"
|
|
+ "\"DATA\":{"
|
|
+ "\"data_dvcd\":\"IO\","
|
|
+ "\"data_scop_len\":\"37\","
|
|
+ "\"BIZ_DATA\":{\"acct_no\":\"987654321\",\"amt\":\"500000\"}"
|
|
+ "}"
|
|
+ "}";
|
|
|
|
/**
|
|
* 비ERP 요청 JSON — corp_tlwn_virt_brcd 미설정 → EZDATA 블록 비활성
|
|
*/
|
|
private static final String NON_ERP_REQ_JSON =
|
|
"{"
|
|
+ "\"HEAD\":{"
|
|
+ "\"nxgn_stnd_idfr\":\"JERA\","
|
|
+ "\"guid\":\"" + TEST_GUID + "\","
|
|
+ "\"guid_prgs_no\":\"1\","
|
|
+ "\"stnd_mesg_ver\":\"R10\","
|
|
+ "\"ortr_guid\":\"" + TEST_GUID + "\","
|
|
+ "\"dman_rspn_dvcd\":\"S\","
|
|
+ "\"if_id\":\"" + TEST_IF_ID + "\","
|
|
+ "\"procs_rslt_dvcd\":\"S\","
|
|
+ "\"tx_id\":\"" + TEST_TX_ID + "\","
|
|
+ "\"chnl_tycd\":\"EAI\","
|
|
+ "\"hmab_dvcd\":\"1\","
|
|
+ "\"trnm_sys_dvcd\":\"OPA\","
|
|
+ "\"frst_trnm_sys_dvcd\":\"OPA\","
|
|
+ "\"sys_env_dvcd\":\"D\","
|
|
+ "\"frst_mesg_dman_dt\":\"20260420\","
|
|
+ "\"frst_mesg_dman_time\":\"120000000\""
|
|
+ "},"
|
|
+ "\"DATA\":{"
|
|
+ "\"data_dvcd\":\"IO\","
|
|
+ "\"data_scop_len\":\"20\","
|
|
+ "\"BIZ_DATA\":{\"acct_no\":\"111222333\"}"
|
|
+ "}"
|
|
+ "}";
|
|
|
|
private StandardMessageManager manager;
|
|
private InterfaceMapper mapper;
|
|
private JsonReader jsonReader;
|
|
private StandardMessageCoordinatorDJB coordinator;
|
|
private ObjectMapper jacksonMapper;
|
|
|
|
@BeforeAll
|
|
void setUpAll() throws Exception {
|
|
PropManager mockPropManager = Mockito.mock(PropManager.class);
|
|
Mockito.when(mockPropManager.getProperty(anyString(), anyString(), anyString()))
|
|
.thenAnswer(new Answer<String>() {
|
|
public String answer(InvocationOnMock inv) { return (String) inv.getArguments()[2]; }
|
|
});
|
|
|
|
EAIServerManager mockServer = Mockito.mock(EAIServerManager.class);
|
|
Mockito.when(mockServer.isPEAIServer()).thenReturn(false);
|
|
Mockito.when(mockServer.isSEAIServer()).thenReturn(false);
|
|
Mockito.when(mockServer.isMCI()).thenReturn(false);
|
|
Mockito.when(mockServer.getLocalServerName()).thenReturn("TEST_SERVER");
|
|
Mockito.when(mockServer.getGroupInstId()).thenReturn("TEST_INST");
|
|
|
|
EAIServiceMonitor mockMonitor = Mockito.mock(EAIServiceMonitor.class);
|
|
Mockito.when(mockMonitor.isTimeOutCodes(anyString())).thenReturn(false);
|
|
Mockito.when(mockMonitor.isBizErrorCodes(anyString())).thenReturn(false);
|
|
|
|
ApplicationContext mockCtx = Mockito.mock(ApplicationContext.class);
|
|
Mockito.when(mockCtx.getBean(EAIServerManager.class)).thenReturn(mockServer);
|
|
Mockito.when(mockCtx.getBean(PropManager.class)).thenReturn(mockPropManager);
|
|
Mockito.when(mockCtx.getBean(EAIServiceMonitor.class)).thenReturn(mockMonitor);
|
|
|
|
Field ctxField = ApplicationContextProvider.class.getDeclaredField("context");
|
|
ctxField.setAccessible(true);
|
|
ctxField.set(null, mockCtx);
|
|
|
|
System.setProperty(StandardMessageManager.STANDARD_MESSAGE_CONFIG,
|
|
"src/test/resources/standard-message-config-test.properties");
|
|
manager = StandardMessageManager.getInstance();
|
|
manager.init();
|
|
}
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
mapper = manager.getMapper();
|
|
jsonReader = (JsonReader) manager.getReader("JSON");
|
|
coordinator = new StandardMessageCoordinatorDJB();
|
|
jacksonMapper = new ObjectMapper();
|
|
}
|
|
|
|
// ================================================================
|
|
// 1. EZDATA 포함 요청 JSON 파싱
|
|
// ================================================================
|
|
|
|
@Test
|
|
void ERP요청_파싱_EZDATA_블록_활성() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertNotNull(msg.findItem("EZDATA"), "EZDATA 블록이 null");
|
|
assertFalse(msg.findItem("EZDATA").isHidden(), "EZDATA 블록이 hidden 상태");
|
|
}
|
|
|
|
@Test
|
|
void ERP요청_파싱_HEAD_corp_tlwn_virt_brcd_ERP() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("ERP", msg.findItemValue("HEAD.corp_tlwn_virt_brcd"),
|
|
"corp_tlwn_virt_brcd가 ERP가 아님");
|
|
}
|
|
|
|
// ================================================================
|
|
// 2. EZDATA 핵심 필드 값 검증
|
|
// ================================================================
|
|
|
|
@Test
|
|
void EZDATA_login_mhod_dvcd_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("1", msg.findItemValue("EZDATA.login_mhod_dvcd"),
|
|
"EZDATA.login_mhod_dvcd 불일치");
|
|
}
|
|
|
|
@Test
|
|
void EZDATA_elfn_bnkn_dvcd_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("01", msg.findItemValue("EZDATA.elfn_bnkn_dvcd"),
|
|
"EZDATA.elfn_bnkn_dvcd 불일치");
|
|
}
|
|
|
|
@Test
|
|
void EZDATA_usr_no_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("USR0000000000001", msg.findItemValue("EZDATA.usr_no").trim(),
|
|
"EZDATA.usr_no 불일치");
|
|
}
|
|
|
|
@Test
|
|
void EZDATA_rgsr_id_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("REG_ID_000000001", msg.findItemValue("EZDATA.rgsr_id").trim(),
|
|
"EZDATA.rgsr_id 불일치");
|
|
}
|
|
|
|
@Test
|
|
void EZDATA_secu_media_dvcd_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("00", msg.findItemValue("EZDATA.secu_media_dvcd"),
|
|
"EZDATA.secu_media_dvcd 불일치");
|
|
}
|
|
|
|
@Test
|
|
void EZDATA_dup_tx_yn_파싱() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
assertEquals("N", msg.findItemValue("EZDATA.dup_tx_yn"),
|
|
"EZDATA.dup_tx_yn 불일치");
|
|
}
|
|
|
|
// ================================================================
|
|
// 3. EZDATA 조건 미충족(비ERP) — EZDATA 블록 직렬화 제외 검증
|
|
// size=0 + refPath/refValue 조건 미충족 → isHidden=true → JSON 제외
|
|
// ================================================================
|
|
|
|
@Test
|
|
void 비ERP요청_파싱_EZDATA_size_0() throws Exception {
|
|
StandardMessage msg = parseNonErpReq();
|
|
|
|
StandardItem ezdataItem = msg.findItem("EZDATA");
|
|
assertTrue(ezdataItem == null || ezdataItem.getSize() == 0,
|
|
"비ERP 요청에서 EZDATA 블록 size는 0이어야 함");
|
|
}
|
|
|
|
@Test
|
|
void 비ERP요청_파싱_JSON_직렬화_EZDATA_제외() throws Exception {
|
|
StandardMessage msg = parseNonErpReq();
|
|
|
|
String json = msg.toJson(false, false);
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertFalse(root.has("EZDATA"), "비ERP 요청 직렬화 JSON에 EZDATA 블록이 없어야 함");
|
|
}
|
|
|
|
@Test
|
|
void 비ERP요청_파싱_BIZ_DATA_정상파싱() throws Exception {
|
|
StandardMessage msg = parseNonErpReq();
|
|
|
|
String bizData = msg.findItemValue("DATA.BIZ_DATA");
|
|
assertNotNull(bizData, "비ERP 요청의 BIZ_DATA가 null");
|
|
JsonNode node = jacksonMapper.readTree(bizData);
|
|
assertEquals("111222333", node.path("acct_no").asText());
|
|
}
|
|
|
|
// ================================================================
|
|
// 4. EZDATA 포함 JSON 왕복(parse → serialize) 일관성
|
|
// ================================================================
|
|
|
|
@Test
|
|
void JSON_왕복_EZDATA_포함_직렬화() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertTrue(root.has("EZDATA"), "JSON 왕복 후 EZDATA 블록 소실");
|
|
}
|
|
|
|
@Test
|
|
void JSON_왕복_EZDATA_usr_no_보존() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertEquals("USR0000000000001",
|
|
root.path("EZDATA").path("usr_no").asText().trim(),
|
|
"JSON 왕복 후 EZDATA.usr_no 불일치");
|
|
}
|
|
|
|
@Test
|
|
void JSON_왕복_HEAD_guid_보존() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertEquals(TEST_GUID, root.path("HEAD").path("guid").asText(),
|
|
"JSON 왕복 후 guid 불일치");
|
|
}
|
|
|
|
@Test
|
|
void JSON_왕복_BIZ_DATA_보존() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
JsonNode bizData = root.path("DATA").get("BIZ_DATA");
|
|
assertNotNull(bizData, "JSON 왕복 후 BIZ_DATA 소실");
|
|
assertEquals("987654321", bizData.path("acct_no").asText(),
|
|
"JSON 왕복 후 BIZ_DATA.acct_no 불일치");
|
|
}
|
|
|
|
// ================================================================
|
|
// 5. coordinateAfterCreateMessageByRule 후 EZDATA 보존
|
|
// ================================================================
|
|
|
|
@Test
|
|
void 표준수신_coordinateAfterCreateMessageByRule_EZDATA_보존() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertTrue(root.has("EZDATA"), "coordinateAfterCreateMessageByRule 후 EZDATA 소실");
|
|
}
|
|
|
|
@Test
|
|
void 표준수신_coordinateAfterCreateMessageByRule_EZDATA_usr_no_보존() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
|
|
|
|
assertEquals("USR0000000000001", msg.findItemValue("EZDATA.usr_no").trim(),
|
|
"coordinateAfterCreateMessageByRule 후 EZDATA.usr_no 변경됨");
|
|
}
|
|
|
|
// ================================================================
|
|
// 6. coordinateBeforeResponse 후 EZDATA 포함 직렬화
|
|
// ================================================================
|
|
|
|
@Test
|
|
void 표준응답생성_coordinateBeforeResponse_EZDATA_포함() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertTrue(root.has("EZDATA"), "coordinateBeforeResponse 후 EZDATA 소실");
|
|
}
|
|
|
|
@Test
|
|
void 표준응답생성_coordinateBeforeResponse_HEAD_mesg_rspn_dt_설정() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
|
|
|
|
String dt = msg.findItemValue("HEAD.mesg_rspn_dt");
|
|
assertNotNull(dt, "mesg_rspn_dt가 null");
|
|
assertTrue(dt.matches("\\d{8}"), "mesg_rspn_dt 형식 오류: " + dt);
|
|
}
|
|
|
|
// ================================================================
|
|
// 7. 오류 응답 생성 시 EZDATA 보존
|
|
// ================================================================
|
|
|
|
@Test
|
|
void 오류응답_EZDATA_포함_JSON_직렬화() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "테스트 오류");
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertTrue(root.has("EZDATA"), "오류응답 JSON에 EZDATA 블록 소실");
|
|
}
|
|
|
|
@Test
|
|
void 오류응답_EZDATA_procs_rslt_dvcd_F() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "테스트 오류");
|
|
|
|
assertEquals("F", msg.findItemValue("HEAD.procs_rslt_dvcd"),
|
|
"오류 응답의 procs_rslt_dvcd는 F여야 함");
|
|
}
|
|
|
|
@Test
|
|
void 오류응답_EZDATA_MSG_블록_포함() throws Exception {
|
|
StandardMessage msg = parseErpReq();
|
|
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "테스트 오류");
|
|
|
|
String json = msg.getDataString(MessageType.JSON, "utf-8");
|
|
JsonNode root = jacksonMapper.readTree(json);
|
|
assertTrue(root.has("MSG"), "오류응답 JSON에 MSG 블록 없음");
|
|
assertEquals("EM", root.path("MSG").path("msg_dvcd").asText(),
|
|
"오류응답 msg_dvcd가 EM이 아님");
|
|
}
|
|
|
|
// ================================================================
|
|
// helper
|
|
// ================================================================
|
|
|
|
private StandardMessage parseErpReq() throws Exception {
|
|
StandardMessage msg = manager.getStandardMessage();
|
|
jsonReader.parse(msg, ERP_REQ_JSON);
|
|
return msg;
|
|
}
|
|
|
|
private StandardMessage parseNonErpReq() throws Exception {
|
|
StandardMessage msg = manager.getStandardMessage();
|
|
jsonReader.parse(msg, NON_ERP_REQ_JSON);
|
|
return msg;
|
|
}
|
|
}
|