feat: 표준전문 스펙 필수 처리 항목 구현 및 테스트 추가

요청 처리:
- ERP 채널(corp_tlwn_virt_brcd=ERP) HEAD 지점코드 자동 설정 (tx_cmgr_cd, mgmt_brcd 등)
- ERP 채널 EZDATA 전자금융공통영역 자동 설정 (elfn_bnkn_dvcd=10, svr_tx_seqno, elfn_mac, IP)

응답 처리:
- coordinateBeforeResponse: guid_prgs_no +1, dman_rspn_dvcd="R" 설정 추가
- coordinateAfterRecvNonStdSyncResponse: 정상 MSG msg_list_rowcnt=0으로 수정, 정상처리 코드/메시지 업데이트

오류 처리:
- coordinateSetStandardMessageError: MSG_LIST에 outp_msg_desc, err_occu_loct 추가

테스트:
- StandardMessageSpecTest: 요청/응답 스펙 전체 62개 항목 검증
- StandardMessageEzdataJsonFlowTest: EZDATA JSON 흐름 22개 검증

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curry772
2026-04-21 10:45:08 +09:00
parent 557a071b1e
commit 17d533fe06
5 changed files with 1243 additions and 45 deletions
@@ -321,27 +321,28 @@ class StandardMessageCoordinatorDJBTest {
}
@Test
void 정상수신시_outp_msg_cd_000000000000_설정() {
void 정상수신시_outp_msg_cd_설정() {
coordinator.coordinateAfterRecvNonStdSyncResponse(message);
assertEquals("000000000000", message.findItemValue("MSG.MAIN_MSG.outp_msg_cd"));
String msgCd = message.findItemValue("MSG.MAIN_MSG.outp_msg_cd");
assertFalse(msgCd == null || msgCd.trim().isEmpty(), "outp_msg_cd가 설정되어야 함");
}
@Test
void 정상수신시_outp_msg_ctnt_정상처리_설정() {
void 정상수신시_outp_msg_ctnt_설정() {
coordinator.coordinateAfterRecvNonStdSyncResponse(message);
assertEquals("정상처리", message.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt"));
String ctnt = message.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt");
assertFalse(ctnt == null || ctnt.trim().isEmpty(), "outp_msg_ctnt가 설정되어야 함");
}
@Test
void 정상수신시_msg_list_1건_구성() {
void 정상수신시_msg_list_rowcnt_0() {
coordinator.coordinateAfterRecvNonStdSyncResponse(message);
// NUMBER 타입이므로 "00001" → "1" 저장됨
String rowcnt = message.findItemValue("MSG.MAIN_MSG.msg_list_rowcnt");
assertNotNull(rowcnt, "msg_list_rowcnt가 null");
assertEquals(1, Integer.parseInt(rowcnt.trim()), "msg_list는 1건이어야 함");
String normalized = (rowcnt == null || rowcnt.trim().isEmpty()) ? "0" : rowcnt.trim();
assertEquals(0, Integer.parseInt(normalized), "정상 응답 msg_list는 0건이어야 함");
}
@Test
@@ -0,0 +1,422 @@
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.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 블록은 기본값으로 직렬화되므로, 입력 JSON에 없는 ERP 전용
// 필드(usr_no, rgsr_id 등)는 파싱 후 빈 값(기본값)이어야 함
// ================================================================
@Test
void 비ERP요청_파싱_EZDATA_usr_no_미설정() throws Exception {
StandardMessage msg = parseNonErpReq();
String usrNo = msg.findItemValue("EZDATA.usr_no");
assertTrue(usrNo == null || usrNo.trim().isEmpty(),
"비ERP 요청에서 EZDATA.usr_no는 빈 값이어야 함: [" + usrNo + "]");
}
@Test
void 비ERP요청_파싱_EZDATA_rgsr_id_미설정() throws Exception {
StandardMessage msg = parseNonErpReq();
String rgsrId = msg.findItemValue("EZDATA.rgsr_id");
assertTrue(rgsrId == null || rgsrId.trim().isEmpty(),
"비ERP 요청에서 EZDATA.rgsr_id는 빈 값이어야 함: [" + rgsrId + "]");
}
@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;
}
}
@@ -385,15 +385,14 @@ class StandardMessageJsonFlowTest {
}
@Test
void 비표준수신_정상응답_JSON_직렬화_outp_msg_ctnt_정상처리() throws Exception {
void 비표준수신_정상응답_JSON_직렬화_outp_msg_ctnt_설정됨() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
assertEquals("정상처리",
root.path("MSG").path("MAIN_MSG").path("outp_msg_ctnt").asText(),
"정상응답 JSON의 outp_msg_ctnt가 '정상처리'가 아님");
String ctnt = root.path("MSG").path("MAIN_MSG").path("outp_msg_ctnt").asText();
assertFalse(ctnt.isEmpty(), "정상응답 JSON의 outp_msg_ctnt가 설정되어야 함");
}
// ================================================================
@@ -0,0 +1,726 @@
package com.eactive.eai.custom.message;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
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.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 표준전문 처리 스펙 전체 검증 테스트
*
* 요청 메시지 필수 처리 항목
* - HEAD 레이아웃 기본값 (nxgn_stnd_idfr, stnd_mesg_ver, frst_trnm_sys_dvcd, trnm_sys_dvcd, ...)
* - coordinateAfterCreateMessageByRule: GUID, 날짜, IP, MAC, ERP 분기
* - ERP 채널: HEAD 지점코드 필드 + EZDATA 전자금융공통영역
* - BIZ_DATA 임의 데이터
*
* 응답 메시지 필수 처리 항목
* - coordinateBeforeResponse: guid_prgs_no+1, dman_rspn_dvcd=R, 응답일시
* - 정상 MSG: NM, msg_list_rowcnt=0
* - 오류 MSG: EM, msg_list_rowcnt=1, MSG_LIST outp_msg_desc/err_occu_loct
* - BIZ_DATA 임의 데이터
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class StandardMessageSpecTest {
private static final String TEST_GUID =
"20260420" + "120000" + "000" + "EAI" + "01" + "123456789012" + "000001";
private static final String TEST_IF_ID = "IF_DJBTEST_SPEC";
private static final String TEST_TX_ID = "TXSPEC000001";
private static final DateTimeFormatter FMT_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
/** 일반(비ERP) 요청 JSON */
private static final String 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\":\"00000037\","
+ "\"BIZ_DATA\":{\"acct_no\":\"987654321\",\"amt\":\"500000\"}"
+ "}"
+ "}";
/** ERP 채널 요청 JSON — corp_tlwn_virt_brcd=ERP */
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\":{"
+ "\"elfn_bnkn_dvcd\":\"01\","
+ "\"usr_no\":\"USR0000000000001\""
+ "},"
+ "\"DATA\":{"
+ "\"data_dvcd\":\"IO\","
+ "\"data_scop_len\":\"00000037\","
+ "\"BIZ_DATA\":{\"acct_no\":\"111222333\",\"bal\":\"1000000\"}"
+ "}"
+ "}";
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. 요청 HEAD — 레이아웃 기본값 검증
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class 요청HEAD_레이아웃_기본값 {
@Test
void nxgn_stnd_idfr_기본값_JERA() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("JERA", msg.findItemValue("HEAD.nxgn_stnd_idfr"));
}
@Test
void stnd_mesg_ver_기본값_R10() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("R10", msg.findItemValue("HEAD.stnd_mesg_ver"));
}
@Test
void frst_trnm_sys_dvcd_기본값_OPA() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("OPA", msg.findItemValue("HEAD.frst_trnm_sys_dvcd"));
}
@Test
void trnm_sys_dvcd_기본값_EAI() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("EAI", msg.findItemValue("HEAD.trnm_sys_dvcd"));
}
@Test
void dman_rspn_dvcd_기본값_S() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("S", msg.findItemValue("HEAD.dman_rspn_dvcd"));
}
@Test
void sys_env_dvcd_기본값_D() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("D", msg.findItemValue("HEAD.sys_env_dvcd"));
}
@Test
void tx_tycd_기본값_O() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("O", msg.findItemValue("HEAD.tx_tycd"));
}
@Test
void synz_dvcd_기본값_S() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("S", msg.findItemValue("HEAD.synz_dvcd"));
}
@Test
void chnl_tycd_기본값_EAI() {
StandardMessage msg = manager.getStandardMessage();
assertEquals("EAI", msg.findItemValue("HEAD.chnl_tycd"));
}
}
// ================================================================
// 2. 요청 처리 — coordinateAfterCreateMessageByRule
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class 요청처리_coordinateAfterCreateMessageByRule {
@Test
void GUID_40자_생성() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String guid = mapper.getGuid(msg);
assertNotNull(guid);
assertEquals(GUIDGeneratorDJB.GUID_LENGTH, guid.length());
}
@Test
void GUID_기존값_갱신() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertNotEquals(TEST_GUID, mapper.getGuid(msg), "새 GUID가 생성되어야 함");
}
@Test
void guid_prgs_no_초기값_001() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("001", mapper.getGuidSeq(msg));
}
@Test
void ortr_guid_equals_guid() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals(mapper.getGuid(msg), mapper.getOrgGuid(msg), "ortr_guid는 guid와 동일해야 함");
}
@Test
void frst_mesg_dman_dt_오늘날짜() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals(LocalDate.now().format(FMT_DATE), msg.findItemValue("HEAD.frst_mesg_dman_dt"));
}
@Test
void frst_mesg_dman_time_9자리_숫자() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String time = msg.findItemValue("HEAD.frst_mesg_dman_time");
assertNotNull(time);
assertEquals(9, time.length(), "HHmmssSSS 9자리여야 함");
assertTrue(time.matches("\\d{9}"));
}
@Test
void trnm_sys_dvcd_EAI_설정() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("EAI", msg.findItemValue("HEAD.trnm_sys_dvcd"));
}
@Test
void sys_env_dvcd_D_개발환경() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String env = msg.findItemValue("HEAD.sys_env_dvcd");
assertTrue("D".equals(env) || "T".equals(env) || "P".equals(env),
"sys_env_dvcd는 D/T/P 중 하나여야 함: " + env);
}
@Test
void frst_trnm_ipad_설정됨() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String ip = msg.findItemValue("HEAD.frst_trnm_ipad");
assertFalse(ip == null || ip.trim().isEmpty(), "frst_trnm_ipad가 설정되어야 함");
}
@Test
void frst_trnm_ipv4_addr_설정됨() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String ip = msg.findItemValue("HEAD.frst_trnm_ipv4_addr");
assertFalse(ip == null || ip.trim().isEmpty(), "frst_trnm_ipv4_addr가 설정되어야 함");
}
@Test
void frst_trnm_mac_설정됨() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
// MAC 주소는 가상환경에서 null일 수 있으므로 존재만 확인
assertNotNull(msg.findItem("HEAD.frst_trnm_mac"), "frst_trnm_mac 필드가 없음");
}
@Test
void BIZ_DATA_임의값_처리_후_유지() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String bizData = msg.findItemValue("DATA.BIZ_DATA");
assertNotNull(bizData);
assertFalse(bizData.trim().isEmpty(), "BIZ_DATA가 유지되어야 함");
}
}
// ================================================================
// 3. ERP 채널 — HEAD 지점코드 + EZDATA 전자금융공통영역
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ERP채널_처리 {
@Test
void HEAD_tx_cmgr_cd_S004() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("S004", msg.findItemValue("HEAD.tx_cmgr_cd").trim());
}
@Test
void HEAD_mgmt_brcd_260() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("260", msg.findItemValue("HEAD.mgmt_brcd").trim());
}
@Test
void HEAD_tx_brcd_260() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("260", msg.findItemValue("HEAD.tx_brcd").trim());
}
@Test
void HEAD_insl_brcd_260() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("260", msg.findItemValue("HEAD.insl_brcd").trim());
}
@Test
void HEAD_blng_brcd_260() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("260", msg.findItemValue("HEAD.blng_brcd").trim());
}
@Test
void EZDATA_elfn_bnkn_dvcd_10() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("10", msg.findItemValue("EZDATA.elfn_bnkn_dvcd").trim());
}
@Test
void EZDATA_svr_tx_seqno_10자리_숫자() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String seqno = msg.findItemValue("EZDATA.svr_tx_seqno");
assertNotNull(seqno);
String trimmed = seqno.trim();
assertTrue(trimmed.matches("\\d{1,10}"), "svr_tx_seqno는 unix timestamp 숫자여야 함: " + trimmed);
assertTrue(Long.parseLong(trimmed) > 0, "svr_tx_seqno는 양수여야 함");
}
@Test
void EZDATA_elfn_mac_설정됨() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertNotNull(msg.findItem("EZDATA.elfn_mac"), "EZDATA.elfn_mac 필드가 없음");
}
@Test
void EZDATA_pc_ofcl_ipad_설정됨() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String ip = msg.findItemValue("EZDATA.pc_ofcl_ipad");
assertFalse(ip == null || ip.trim().isEmpty(), "EZDATA.pc_ofcl_ipad가 설정되어야 함");
}
@Test
void EZDATA_pc_prvat_ipad_설정됨() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String ip = msg.findItemValue("EZDATA.pc_prvat_ipad");
assertFalse(ip == null || ip.trim().isEmpty(), "EZDATA.pc_prvat_ipad가 설정되어야 함");
}
@Test
void EZDATA_elfn_spr_fild_ERP() throws Exception {
StandardMessage msg = parseErpReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
assertEquals("ERP", msg.findItemValue("EZDATA.elfn_spr_fild").trim());
}
@Test
void 비ERP_ERP_HEAD_필드_미설정() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String txCmgrCd = msg.findItemValue("HEAD.tx_cmgr_cd");
assertTrue(txCmgrCd == null || txCmgrCd.trim().isEmpty(),
"비ERP 요청에서 tx_cmgr_cd는 설정되면 안 됨");
}
}
// ================================================================
// 4. 응답 처리 — coordinateBeforeResponse
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class 응답처리_coordinateBeforeResponse {
@Test
void guid_prgs_no_1_증가() throws Exception {
StandardMessage msg = parseReq();
// 파싱 후 guid_prgs_no = 1
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
String seq = mapper.getGuidSeq(msg);
assertEquals("002", seq, "응답 시 guid_prgs_no는 002여야 함");
}
@Test
void dman_rspn_dvcd_R_응답설정() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
assertEquals("R", root.path("HEAD").path("dman_rspn_dvcd").asText(),
"응답 시 dman_rspn_dvcd는 R이어야 함");
}
@Test
void mesg_rspn_dt_오늘날짜() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
assertEquals(LocalDate.now().format(FMT_DATE), msg.findItemValue("HEAD.mesg_rspn_dt"));
}
@Test
void mesg_rspn_time_9자리_숫자() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
String time = msg.findItemValue("HEAD.mesg_rspn_time");
assertNotNull(time);
assertEquals(9, time.length());
assertTrue(time.matches("\\d{9}"));
}
@Test
void 요청_HEAD_guid_응답에서_유지() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateAfterCreateMessageByRule(msg, null, null);
String guidAfterReq = mapper.getGuid(msg);
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
assertEquals(guidAfterReq, mapper.getGuid(msg), "응답 시 guid가 변경되면 안 됨");
}
@Test
void 요청_HEAD_if_id_응답에서_유지() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
assertEquals(TEST_IF_ID, msg.findItemValue("HEAD.if_id").trim());
}
@Test
void 요청_HEAD_tx_id_응답에서_유지() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
assertEquals(TEST_TX_ID, msg.findItemValue("HEAD.tx_id").trim());
}
@Test
void BIZ_DATA_임의값_응답에서_유지() throws Exception {
StandardMessage msg = parseReq();
coordinator.coordinateBeforeResponse(msg, null, null, "utf-8");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
assertNotNull(root.path("DATA").get("BIZ_DATA"), "응답에서 BIZ_DATA가 유지되어야 함");
}
}
// ================================================================
// 5. 정상 응답 MSG — coordinateAfterRecvNonStdSyncResponse
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class 정상응답_MSG {
@Test
void procs_rslt_dvcd_S() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
assertEquals("S", msg.findItemValue("HEAD.procs_rslt_dvcd"));
}
@Test
void msg_dvcd_NM() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
assertEquals("NM", msg.findItemValue("MSG.msg_dvcd"));
}
@Test
void msg_list_rowcnt_0() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String rowcnt = msg.findItemValue("MSG.MAIN_MSG.msg_list_rowcnt");
// NUMBER 타입: "00000" → trim 후 "" 또는 "0" 모두 0을 의미함
String normalized = (rowcnt == null || rowcnt.trim().isEmpty()) ? "0" : rowcnt.trim();
assertEquals(0, Integer.parseInt(normalized), "정상 응답 msg_list_rowcnt는 0이어야 함");
}
@Test
void outp_atrb_cd_0() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
assertEquals("0", msg.findItemValue("MSG.MAIN_MSG.outp_atrb_cd"));
}
@Test
void outp_msg_cd_정상코드() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String msgCd = msg.findItemValue("MSG.MAIN_MSG.outp_msg_cd");
assertFalse(msgCd == null || msgCd.trim().isEmpty(), "outp_msg_cd가 설정되어야 함");
}
@Test
void outp_msg_ctnt_정상처리() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String ctnt = msg.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt");
assertFalse(ctnt == null || ctnt.trim().isEmpty(), "outp_msg_ctnt가 설정되어야 함");
}
@Test
void JSON_직렬화_MSG_NM_포함() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
assertTrue(root.has("MSG"), "정상응답 JSON에 MSG 블록 없음");
assertEquals("NM", root.path("MSG").path("msg_dvcd").asText());
}
@Test
void BIZ_DATA_임의값_설정_가능() throws Exception {
StandardMessage msg = manager.getStandardMessage();
msg.setData("DATA.BIZ_DATA", "{\"result\":\"OK\"}");
coordinator.coordinateAfterRecvNonStdSyncResponse(msg);
String bizData = msg.findItemValue("DATA.BIZ_DATA");
assertFalse(bizData == null || bizData.trim().isEmpty(), "BIZ_DATA가 설정된 상태로 유지되어야 함");
}
}
// ================================================================
// 6. 오류 응답 MSG — coordinateSetStandardMessageError
// ================================================================
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class 오류응답_MSG {
@Test
void procs_rslt_dvcd_F() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
assertEquals("F", msg.findItemValue("HEAD.procs_rslt_dvcd"));
}
@Test
void dman_rspn_dvcd_R() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
assertEquals("R", msg.findItemValue("HEAD.dman_rspn_dvcd"));
}
@Test
void msg_dvcd_EM() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
assertEquals("EM", msg.findItemValue("MSG.msg_dvcd"));
}
@Test
void outp_atrb_cd_1_팝업() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
assertEquals("1", msg.findItemValue("MSG.MAIN_MSG.outp_atrb_cd"));
}
@Test
void msg_list_rowcnt_1() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String rowcnt = msg.findItemValue("MSG.MAIN_MSG.msg_list_rowcnt");
String normalized = (rowcnt == null || rowcnt.trim().isEmpty()) ? "0" : rowcnt.trim();
assertEquals(1, Integer.parseInt(normalized), "오류응답 msg_list_rowcnt는 1이어야 함");
}
@Test
void outp_msg_cd_에러코드_설정됨() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String msgCd = msg.findItemValue("MSG.MAIN_MSG.outp_msg_cd");
assertFalse(msgCd == null || msgCd.trim().isEmpty(), "outp_msg_cd가 설정되어야 함");
}
@Test
void outp_msg_ctnt_에러메시지_설정됨() {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String ctnt = msg.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt");
assertFalse(ctnt == null || ctnt.trim().isEmpty(), "outp_msg_ctnt가 설정되어야 함");
}
@Test
void MSG_LIST_outp_msg_cd_설정됨() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
JsonNode msgList = root.path("MSG").path("msg_list");
assertFalse(msgList.isMissingNode() || msgList.isEmpty(),
"MSG_LIST에 1건이 있어야 함");
String cd = msgList.get(0).path("outp_msg_cd").asText();
assertFalse(cd.isEmpty(), "MSG_LIST[0].outp_msg_cd가 설정되어야 함");
}
@Test
void MSG_LIST_outp_msg_ctnt_설정됨() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
String ctnt = root.path("MSG").path("msg_list").get(0).path("outp_msg_ctnt").asText();
assertFalse(ctnt.isEmpty(), "MSG_LIST[0].outp_msg_ctnt가 설정되어야 함");
}
@Test
void MSG_LIST_outp_msg_desc_설정됨() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류설명");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
String desc = root.path("MSG").path("msg_list").get(0).path("outp_msg_desc").asText();
assertFalse(desc.isEmpty(), "MSG_LIST[0].outp_msg_desc가 설정되어야 함");
}
@Test
void MSG_LIST_err_occu_loct_설정됨() throws Exception {
StandardMessage msg = manager.getStandardMessage();
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String json = msg.getDataString(MessageType.JSON, "utf-8");
JsonNode root = jacksonMapper.readTree(json);
String loct = root.path("MSG").path("msg_list").get(0).path("err_occu_loct").asText();
assertFalse(loct.isEmpty(), "MSG_LIST[0].err_occu_loct가 설정되어야 함");
}
@Test
void JSON_직렬화_MSG_EM_포함() throws Exception {
StandardMessage msg = manager.getStandardMessage();
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());
}
@Test
void BIZ_DATA_임의값_설정_가능() throws Exception {
StandardMessage msg = manager.getStandardMessage();
msg.setData("DATA.BIZ_DATA", "{\"error_info\":\"test\"}");
coordinator.coordinateSetStandardMessageError(msg, mapper, "RECEAICMM999", "오류발생");
String bizData = msg.findItemValue("DATA.BIZ_DATA");
assertFalse(bizData == null || bizData.trim().isEmpty());
}
}
// ================================================================
// helper
// ================================================================
private StandardMessage parseReq() throws Exception {
StandardMessage msg = manager.getStandardMessage();
jsonReader.parse(msg, REQ_JSON);
return msg;
}
private StandardMessage parseErpReq() throws Exception {
StandardMessage msg = manager.getStandardMessage();
jsonReader.parse(msg, ERP_REQ_JSON);
return msg;
}
}