Files
eapim-online/src/test/java/com/eactive/eai/custom/message/StandardMessageEzdataJsonFlowTest.java
T
curry772 2d17387def fix: EZDATA size=0으로 변경하여 비ERP 요청 시 직렬화 제외
- 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>
2026-04-21 13:13:55 +09:00

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;
}
}