feat: DJBank 차세대 표준전문(R10) 초기 구현
- standard-layout-djb.csv: HEAD(평면구조)/EZDATA/MSG/DATA/전문종료부(@JJ) 레이아웃 정의 - standard-message-mapping-config-djb.properties: 논리키 → 필드경로 매핑 (GUID 40자, guid_prgs_no 별도 필드 등) - standard-message-config.properties: DJB 클래스로 전환 (CSV 방식) - GUIDGeneratorDJB: 40자 GUID 생성 (일자+시간+밀리초+시스템코드+노드+세션+Random) - InterfaceMapperDJB: GUID 40자, guid_prgs_no 독립 필드, 응답코드 S/F 변환 - StandardMessageCoordinatorDJB: 전문 생성/응답/에러 각 단계 후처리 - 단위테스트 45개 전체 통과 (GUIDGenerator/InterfaceMapper/Layout 검증) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package com.eactive.eai.custom.message;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class GUIDGeneratorDJBTest {
|
||||
|
||||
@Test
|
||||
void guid_길이는_40자여야_한다() {
|
||||
String guid = GUIDGeneratorDJB.getGUID("EAI");
|
||||
assertEquals(40, guid.length(), "GUID 길이는 40자: " + guid);
|
||||
}
|
||||
|
||||
@Test
|
||||
void guid_시스템코드_3자로_정규화된다() {
|
||||
// 짧은 코드
|
||||
String guid1 = GUIDGeneratorDJB.getGUID("EA");
|
||||
assertEquals(40, guid1.length());
|
||||
|
||||
// 긴 코드 (잘림)
|
||||
String guid2 = GUIDGeneratorDJB.getGUID("EAIFEP");
|
||||
assertEquals(40, guid2.length());
|
||||
|
||||
// null
|
||||
String guid3 = GUIDGeneratorDJB.getGUID(null);
|
||||
assertEquals(40, guid3.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
void guid_구성_형식_검증() {
|
||||
String guid = GUIDGeneratorDJB.getGUID("EAI");
|
||||
// 일자(8) + 시간(6) + 밀리초(3) + 시스템코드(3) + 노드번호(2) + 세션ID(12) + Random(6)
|
||||
String date = guid.substring(0, 8);
|
||||
String time = guid.substring(8, 14);
|
||||
String millis = guid.substring(14, 17);
|
||||
String sysCode = guid.substring(17, 20);
|
||||
String nodeNo = guid.substring(20, 22);
|
||||
String sessId = guid.substring(22, 34);
|
||||
String random = guid.substring(34, 40);
|
||||
|
||||
// 일자: 숫자 8자리
|
||||
assertDoesNotThrow(() -> Long.parseLong(date), "일자 부분이 숫자가 아님: " + date);
|
||||
assertTrue(date.matches("\\d{8}"), "일자 형식 오류: " + date);
|
||||
|
||||
// 시간: 숫자 6자리
|
||||
assertTrue(time.matches("\\d{6}"), "시간 형식 오류: " + time);
|
||||
|
||||
// 밀리초: 숫자 3자리
|
||||
assertTrue(millis.matches("\\d{3}"), "밀리초 형식 오류: " + millis);
|
||||
|
||||
// 시스템코드: 3자리 영문/숫자
|
||||
assertEquals(3, sysCode.length(), "시스템코드 길이 오류: " + sysCode);
|
||||
|
||||
// 노드번호: 2자리
|
||||
assertEquals(2, nodeNo.length(), "노드번호 길이 오류: " + nodeNo);
|
||||
|
||||
// 세션ID: 12자리
|
||||
assertEquals(12, sessId.length(), "세션ID 길이 오류: " + sessId);
|
||||
|
||||
// Random: 숫자 6자리
|
||||
assertTrue(random.matches("\\d{6}"), "Random 형식 오류: " + random);
|
||||
}
|
||||
|
||||
@Test
|
||||
void guid_연속_생성시_유니크해야_한다() {
|
||||
Set<String> guids = new HashSet<>();
|
||||
int count = 1000;
|
||||
for (int i = 0; i < count; i++) {
|
||||
guids.add(GUIDGeneratorDJB.getGUID("EAI"));
|
||||
}
|
||||
assertEquals(count, guids.size(), "GUID 중복 발생");
|
||||
}
|
||||
|
||||
@Test
|
||||
void guid_상수_길이값_확인() {
|
||||
assertEquals(40, GUIDGeneratorDJB.GUID_LENGTH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package com.eactive.eai.custom.message;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.eactive.eai.message.StandardMessage;
|
||||
import com.eactive.eai.message.StandardMessageUtil;
|
||||
import com.ext.eai.common.stdmessage.STDMessageKeys;
|
||||
|
||||
class InterfaceMapperDJBTest {
|
||||
|
||||
private InterfaceMapperDJB mapper;
|
||||
private StandardMessage message;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
// CSV에서 표준전문 레이아웃 로드
|
||||
message = StandardMessageUtil.generateMessageFromCsvFile(
|
||||
"src/main/resources/standard-layout-djb.csv");
|
||||
assertNotNull(message, "standard-layout-djb.csv 로드 실패");
|
||||
message.setReadPosition(0);
|
||||
|
||||
// 매핑 설정 로드
|
||||
Properties props = new Properties();
|
||||
try (java.io.InputStream in = getClass().getClassLoader()
|
||||
.getResourceAsStream("standard-message-mapping-config-djb.properties")) {
|
||||
assertNotNull(in, "standard-message-mapping-config-djb.properties 로드 실패");
|
||||
props.load(in);
|
||||
}
|
||||
|
||||
HashMap<String, String> pathMap = new HashMap<>();
|
||||
for (String key : props.stringPropertyNames()) {
|
||||
pathMap.put(key.trim(), props.getProperty(key).trim());
|
||||
}
|
||||
|
||||
mapper = new InterfaceMapperDJB();
|
||||
mapper.initPathMap(pathMap);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// GUID
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void setGuid_40자_정상_설정() {
|
||||
String guid = GUIDGeneratorDJB.getGUID("EAI");
|
||||
mapper.setGuid(message, guid);
|
||||
assertEquals(guid, mapper.getGuid(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setGuid_40자_아닌경우_예외발생() {
|
||||
assertThrows(RuntimeException.class, () -> mapper.setGuid(message, "SHORT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setGuid_null이면_예외발생() {
|
||||
assertThrows(RuntimeException.class, () -> mapper.setGuid(message, null));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// GUID 진행번호 (guid_prgs_no - 별도 필드)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void guidSeq_초기값_및_nextGuidSeq_증가() {
|
||||
// 초기값 설정
|
||||
mapper.setGuidSeq(message, "001");
|
||||
assertEquals("001", mapper.getGuidSeq(message));
|
||||
|
||||
// +1 증가
|
||||
String next = mapper.nextGuidSeq(message);
|
||||
assertEquals("002", next);
|
||||
assertEquals("002", mapper.getGuidSeq(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nextGuidSeq_3자리_zero_padding() {
|
||||
mapper.setGuidSeq(message, "009");
|
||||
assertEquals("010", mapper.nextGuidSeq(message));
|
||||
|
||||
mapper.setGuidSeq(message, "099");
|
||||
assertEquals("100", mapper.nextGuidSeq(message));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 원거래 GUID (ortr_guid)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void orgGuid_설정_조회() {
|
||||
String guid = GUIDGeneratorDJB.getGUID("EAI");
|
||||
mapper.setOrgGuid(message, guid);
|
||||
assertEquals(guid, mapper.getOrgGuid(message));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 처리결과구분코드 (S/F ↔ 엔진 내부 NR/ER)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void setResponseType_정상_NR_to_S() {
|
||||
mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_N); // "NR"
|
||||
assertEquals("S", message.findItemValue("HEAD.procs_rslt_dvcd"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setResponseType_오류_ER_to_F() {
|
||||
mapper.setResponseType(message, STDMessageKeys.RESPONSE_TYPE_CODE_E); // "ER"
|
||||
assertEquals("F", message.findItemValue("HEAD.procs_rslt_dvcd"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getResponseType_S_to_NR() {
|
||||
message.setData("HEAD.procs_rslt_dvcd", "S");
|
||||
assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_N, mapper.getResponseType(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getResponseType_F_to_ER() {
|
||||
message.setData("HEAD.procs_rslt_dvcd", "F");
|
||||
assertEquals(STDMessageKeys.RESPONSE_TYPE_CODE_E, mapper.getResponseType(message));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 원거래복원여부 (Y/N ↔ 엔진 내부 1/0)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void recoverYn_Y면_1반환() {
|
||||
message.setData("HEAD.ortr_restr_yn", "Y");
|
||||
assertEquals("1", mapper.getRecoverYn(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void recoverYn_N면_0반환() {
|
||||
message.setData("HEAD.ortr_restr_yn", "N");
|
||||
assertEquals("0", mapper.getRecoverYn(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setRecoverYn_1이면_Y설정() {
|
||||
mapper.setRecoverYn(message, "1");
|
||||
assertEquals("Y", message.findItemValue("HEAD.ortr_restr_yn"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void setRecoverYn_0이면_N설정() {
|
||||
mapper.setRecoverYn(message, "0");
|
||||
assertEquals("N", message.findItemValue("HEAD.ortr_restr_yn"));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 인터페이스ID (trim)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void getInterfaceId_공백_trim() {
|
||||
message.setData("HEAD.if_id", " IF001 ");
|
||||
assertEquals("IF001", mapper.getInterfaceId(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInterfaceId_null이면_빈문자열() {
|
||||
// 초기 공백상태
|
||||
String ifId = mapper.getInterfaceId(message);
|
||||
assertNotNull(ifId);
|
||||
assertEquals("", ifId.trim());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// EAI 서비스코드 조합
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void getEaiSvcCode_인터페이스ID_요청응답_내외구분_조합() {
|
||||
message.setData("HEAD.if_id", "IF_TEST_001");
|
||||
message.setData("HEAD.dman_rspn_dvcd", "S");
|
||||
message.setData("HEAD.hmab_dvcd", "1");
|
||||
|
||||
String svcCode = mapper.getEaiSvcCode(message);
|
||||
assertTrue(svcCode.startsWith("IF_TEST_001"), "EAI 서비스코드: " + svcCode);
|
||||
assertTrue(svcCode.contains("S"), "요청응답구분 포함: " + svcCode);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 필드 경로 기본 동작 확인 (매핑 설정 유효성)
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void sendRecvDivision_설정_조회() {
|
||||
mapper.setSendRecvDivision(message, "R");
|
||||
assertEquals("R", mapper.getSendRecvDivision(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void inExDivision_설정_조회() {
|
||||
mapper.setInExDivision(message, "1");
|
||||
assertEquals("1", mapper.getInExDivision(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorCode_설정_조회() {
|
||||
mapper.setErrorCode(message, "ERR001");
|
||||
assertEquals("ERR001", mapper.getErrorCode(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorMsg_설정_조회() {
|
||||
mapper.setErrorMsg(message, "오류가 발생했습니다.");
|
||||
assertEquals("오류가 발생했습니다.", mapper.getErrorMsg(message));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package com.eactive.eai.custom.message;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.eactive.eai.message.StandardItem;
|
||||
import com.eactive.eai.message.StandardMessage;
|
||||
import com.eactive.eai.message.StandardMessageUtil;
|
||||
|
||||
/**
|
||||
* standard-layout-djb.csv 로드 및 전문 구조 검증
|
||||
*/
|
||||
class StandardLayoutDJBTest {
|
||||
|
||||
private StandardMessage message;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
message = StandardMessageUtil.generateMessageFromCsvFile(
|
||||
"src/main/resources/standard-layout-djb.csv");
|
||||
assertNotNull(message, "standard-layout-djb.csv 로드 실패");
|
||||
message.setReadPosition(0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 최상위 블록 존재 여부
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void HEAD_블록_존재() {
|
||||
assertNotNull(message.findItem("HEAD"), "HEAD 블록 없음");
|
||||
}
|
||||
|
||||
@Test
|
||||
void EZDATA_블록_존재() {
|
||||
assertNotNull(message.findItem("EZDATA"), "EZDATA 블록 없음");
|
||||
}
|
||||
|
||||
@Test
|
||||
void MSG_블록_존재() {
|
||||
assertNotNull(message.findItem("MSG"), "MSG 블록 없음");
|
||||
}
|
||||
|
||||
@Test
|
||||
void DATA_블록_존재() {
|
||||
assertNotNull(message.findItem("DATA"), "DATA 블록 없음");
|
||||
}
|
||||
|
||||
@Test
|
||||
void 전문종료부_존재() {
|
||||
assertNotNull(message.findItem("MESG_END_IDFR_VAL"), "전문종료부 없음");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// HEAD 핵심 필드 검증
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void HEAD_guid_필드_존재_및_길이40() {
|
||||
StandardItem guidItem = message.findItem("HEAD.guid");
|
||||
assertNotNull(guidItem, "HEAD.guid 필드 없음");
|
||||
assertEquals(40, guidItem.getLength(), "HEAD.guid 길이는 40자여야 함");
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_guid_prgs_no_필드_존재() {
|
||||
StandardItem item = message.findItem("HEAD.guid_prgs_no");
|
||||
assertNotNull(item, "HEAD.guid_prgs_no 필드 없음");
|
||||
assertEquals(3, item.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_nxgn_stnd_idfr_기본값_JERA() {
|
||||
StandardItem item = message.findItem("HEAD.nxgn_stnd_idfr");
|
||||
assertNotNull(item, "HEAD.nxgn_stnd_idfr 필드 없음");
|
||||
assertEquals(4, item.getLength());
|
||||
assertEquals("JERA", item.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_ortr_guid_필드_존재_및_길이40() {
|
||||
StandardItem item = message.findItem("HEAD.ortr_guid");
|
||||
assertNotNull(item, "HEAD.ortr_guid 필드 없음");
|
||||
assertEquals(40, item.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_if_id_필드_길이30() {
|
||||
StandardItem item = message.findItem("HEAD.if_id");
|
||||
assertNotNull(item, "HEAD.if_id 필드 없음");
|
||||
assertEquals(30, item.getLength(), "HEAD.if_id 길이는 30자여야 함 (기존 20자에서 변경)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_dman_rspn_dvcd_기본값_S() {
|
||||
StandardItem item = message.findItem("HEAD.dman_rspn_dvcd");
|
||||
assertNotNull(item, "HEAD.dman_rspn_dvcd 필드 없음");
|
||||
assertEquals("S", item.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_procs_rslt_dvcd_기본값_S() {
|
||||
StandardItem item = message.findItem("HEAD.procs_rslt_dvcd");
|
||||
assertNotNull(item, "HEAD.procs_rslt_dvcd 필드 없음");
|
||||
assertEquals("S", item.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void HEAD_trnm_sys_dvcd_기본값_EAI() {
|
||||
StandardItem item = message.findItem("HEAD.trnm_sys_dvcd");
|
||||
assertNotNull(item, "HEAD.trnm_sys_dvcd 필드 없음");
|
||||
assertEquals("EAI", item.getValue());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// MSG 영역 구조 검증
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void MSG_MAIN_MSG_블록_존재() {
|
||||
assertNotNull(message.findItem("MSG.MAIN_MSG"), "MSG.MAIN_MSG 블록 없음");
|
||||
}
|
||||
|
||||
@Test
|
||||
void MSG_outp_msg_cd_길이12() {
|
||||
StandardItem item = message.findItem("MSG.MAIN_MSG.outp_msg_cd");
|
||||
assertNotNull(item, "MSG.MAIN_MSG.outp_msg_cd 필드 없음");
|
||||
assertEquals(12, item.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
void MSG_msg_list_Grid_존재() {
|
||||
assertNotNull(message.findItem("MSG.msg_list"), "MSG.msg_list Grid 없음");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// DATA 영역 구조 검증
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void DATA_BIZ_DATA_존재() {
|
||||
assertNotNull(message.findItem("DATA.BIZ_DATA"), "DATA.BIZ_DATA 없음");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// setData / findItemValue 기본 동작
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void HEAD_필드_setData_findItemValue() {
|
||||
String guid40 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; // 40자
|
||||
message.setData("HEAD.guid", guid40);
|
||||
assertEquals(guid40, message.findItemValue("HEAD.guid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void MSG_필드_setData_findItemValue() {
|
||||
message.setData("MSG.MAIN_MSG.outp_msg_ctnt", "테스트오류메시지");
|
||||
assertEquals("테스트오류메시지", message.findItemValue("MSG.MAIN_MSG.outp_msg_ctnt"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user