diff --git a/src/main/java/com/eactive/eai/transformer/SystemKeys.java b/src/main/java/com/eactive/eai/transformer/SystemKeys.java index 725b1c3..ca36a2b 100644 --- a/src/main/java/com/eactive/eai/transformer/SystemKeys.java +++ b/src/main/java/com/eactive/eai/transformer/SystemKeys.java @@ -86,7 +86,7 @@ public class SystemKeys { } public static boolean isValidationEnabled() { - return false; + return validationEnabled; } public static boolean isAddDecimalPointEnabled() { diff --git a/src/test/java/com/eactive/eai/transformer/JSONMessageValidationTest.java b/src/test/java/com/eactive/eai/transformer/JSONMessageValidationTest.java new file mode 100644 index 0000000..5e6c908 --- /dev/null +++ b/src/test/java/com/eactive/eai/transformer/JSONMessageValidationTest.java @@ -0,0 +1,213 @@ +package com.eactive.eai.transformer; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.jdbc.Sql; + +import com.eactive.eai.transformer.engine.TransformEngine; +import com.eactive.eai.transformer.function.jpa.TransformJPATestConfiguration; +import com.eactive.eai.transformer.message.InvalidDataTypeException; +import com.eactive.eai.transformer.message.Message; +import com.eactive.eai.transformer.message.MessageFactory; +import com.eactive.eai.transformer.message.MessageSetDataException; + +/** + * JSONMessage 필드 validation 단위테스트 + * + * 테스트 대상 레이아웃: EAI_UJSONTYPE_REQ1 + * - INT_VALUE : INT, length=5, decimal=0 + * - LONG_VALUE : LONG, length=10, decimal=0 + * - BIG_VALUE : BIGDECIMAL, length=10, decimal=5 → 정수부 최대 4자리 + * - BIG15_VALUE : BIGDECIMAL, length=15, decimal=0 → 정수부 최대 15자리 + * + * 검증 시나리오 + * 1) 타입 불일치 — 숫자형 필드에 비숫자 문자열 입력 시 setData() 에서 즉시 오류 + * 2) 길이 초과 — BigDecimal 정수부/소수부 자릿수 초과 시 getData() 에서 오류 + * (SystemKeys.TRANSFROMER_VALIDATION=true 필요) + */ +@DataJpaTest +@ContextConfiguration(classes = { TransformJPATestConfiguration.class }) +@Sql({ + "/com/eactive/eai/transformer/init_tseaitr06.sql", + "/com/eactive/eai/transformer/init_json_validation.sql" +}) +@DisplayName("JSONMessage Validation 테스트") +class JSONMessageValidationTest { + + @Autowired + TransformEngine engine; + + @BeforeEach + void setUp() { + try { + if (!engine.isStarted()) { + engine.start(); + } + } catch (Exception e) { + assumeTrue(false, "TransformEngine 시작 실패: " + e.getMessage()); + } + } + + @AfterEach + void tearDown() { + System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "false"); + SystemKeys.reload(); + } + + // ───────────────────────────────────────────────────────────────── + // 1. 타입 불일치 테스트 — setData() 시점에 오류 발생 + // ───────────────────────────────────────────────────────────────── + + @Test + @DisplayName("INT 타입 필드에 비숫자 문자열 입력 → NumberFormatException") + void testIntFieldTypeError() { + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"INT_VALUE\":\"abc\"}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + + MessageSetDataException ex = assertThrows( + MessageSetDataException.class, + () -> msg.setData(data) + ); + assertTrue(containsCause(ex, NumberFormatException.class), + "원인이 NumberFormatException이어야 합니다"); + } + + @Test + @DisplayName("LONG 타입 필드에 비숫자 문자열 입력 → NumberFormatException") + void testLongFieldTypeError() { + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"LONG_VALUE\":\"not_a_number\"}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + + MessageSetDataException ex = assertThrows( + MessageSetDataException.class, + () -> msg.setData(data) + ); + assertTrue(containsCause(ex, NumberFormatException.class), + "원인이 NumberFormatException이어야 합니다"); + } + + @Test + @DisplayName("BIGDECIMAL 타입 필드에 비숫자 문자열 입력 → NumberFormatException") + void testBigDecimalFieldTypeError() { + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":\"invalid_decimal\"}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + + MessageSetDataException ex = assertThrows( + MessageSetDataException.class, + () -> msg.setData(data) + ); + assertTrue(containsCause(ex, NumberFormatException.class), + "원인이 NumberFormatException이어야 합니다"); + } + + // ───────────────────────────────────────────────────────────────── + // 2. 숫자형 길이 초과 테스트 — getData() 시점에 오류 발생 + // transformer.validation=true 설정 필요 + // ───────────────────────────────────────────────────────────────── + + @Test + @DisplayName("BIG_VALUE 정수부 초과(5자리 > 4자리 제한) → InvalidDataTypeException") + void testBigDecimalIntegerPartOverflow() throws Exception { + enableValidation(); + + // 정수부 5자리(12345) → 제한(4자리) 초과 + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":12345.12345}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + msg.setData(data); + + InvalidDataTypeException ex = assertThrows( + InvalidDataTypeException.class, + () -> msg.getData() + ); + assertTrue(containsMessage(ex, "Invalid decimal point format"), + "'Invalid decimal point format' 메시지가 포함되어야 합니다"); + } + + @Test + @DisplayName("BIG_VALUE 소수부 초과(6자리 > 5자리 제한) → InvalidDataTypeException") + void testBigDecimalFractionalPartOverflow() throws Exception { + enableValidation(); + + // 소수부 6자리(123456) → 제한(5자리) 초과 + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":1234.123456}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + msg.setData(data); + + InvalidDataTypeException ex = assertThrows( + InvalidDataTypeException.class, + () -> msg.getData() + ); + assertTrue(containsMessage(ex, "Invalid decimal point format"), + "'Invalid decimal point format' 메시지가 포함되어야 합니다"); + } + + @Test + @DisplayName("BIG15_VALUE 정수부 초과(16자리 > 15자리 제한) → InvalidDataTypeException") + void testBigDecimalIntegerOnlyOverflow() throws Exception { + enableValidation(); + + // 정수부 16자리 → 제한(15자리) 초과 + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG15_VALUE\":1234567890123456}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + msg.setData(data); + + InvalidDataTypeException ex = assertThrows( + InvalidDataTypeException.class, + () -> msg.getData() + ); + assertTrue(containsMessage(ex, "Invalid decimal point format"), + "'Invalid decimal point format' 메시지가 포함되어야 합니다"); + } + + @Test + @DisplayName("BIG_VALUE 정상 범위(정수부 4자리 + 소수부 5자리) → 정상 처리") + void testBigDecimalWithinBounds() throws Exception { + enableValidation(); + + // 정수부 4자리 + 소수부 5자리 → 정상 + String data = "{\"EAI_UJSONTYPE_REQ1\":{\"BIG_VALUE\":1234.12345}}"; + Message msg = MessageFactory.getFactory().getMessage("EAI_UJSONTYPE_REQ1"); + msg.setData(data); + + String result = (String) msg.getData(); + assertNotNull(result, "결과값이 null이 아니어야 합니다"); + assertTrue(result.contains("BIG_VALUE"), "BIG_VALUE가 결과에 포함되어야 합니다"); + } + + // ───────────────────────────────────────────────────────────────── + // 유틸 메서드 + // ───────────────────────────────────────────────────────────────── + + private void enableValidation() { + System.setProperty(SystemKeys.TRANSFROMER_VALIDATION, "true"); + SystemKeys.reload(); + } + + private boolean containsCause(Throwable e, Class causeClass) { + Throwable t = e; + while (t != null) { + if (causeClass.isInstance(t)) return true; + t = t.getCause(); + } + return false; + } + + private boolean containsMessage(Throwable e, String keyword) { + Throwable t = e; + while (t != null) { + if (t.getMessage() != null && t.getMessage().contains(keyword)) return true; + t = t.getCause(); + } + return false; + } +} diff --git a/src/test/resources/com/eactive/eai/transformer/init_json_validation.sql b/src/test/resources/com/eactive/eai/transformer/init_json_validation.sql new file mode 100644 index 0000000..35334e4 --- /dev/null +++ b/src/test/resources/com/eactive/eai/transformer/init_json_validation.sql @@ -0,0 +1,9 @@ +INSERT INTO tseaitr07 (loutname,loutptrnname,loutdesc,lastamndhms,eaibzwkdstcd,uapplname,sysintfacname,eaisevrdstcd,modfimgtstusdstcd,useyn,verinfo,author) VALUES + ('EAI_UJSONTYPE_REQ1', 'JSON', 'JSON 타입 검증 테스트', '2026042210000000', 'TST', ' ', ' ', 'E', ' ', '1', '00001', 'admin'); + +INSERT INTO TSEAITR08 (loutname,loutitemname,loutitemserno,loutitemidname,parntloutitemidname,loutitemdesc,loutitemnodeptrnidname,loutitemptrnidname,loutitempathname,loutitemlencnt,loutitemrefinfo,loutitemrefinfo2,loutitemoccurptrndstcd,loutitemmaxoccurnoitm,loutitemminoccurnoitm,loutitembascval,loutitemmskyn,loutdptcnt,decptlencnt,loutitemrefptrnidname,loutitemmasklength,multilang,loutitemmaskoffset) VALUES + ('EAI_UJSONTYPE_REQ1', 'EAI_UJSONTYPE_REQ1', 0, 9000, 0, 'JSON 타입 검증 테스트', 2201, 2100, NULL, 0, NULL, NULL, NULL, 0, 0, NULL, NULL, 1, 0, NULL, NULL, NULL, NULL), + ('EAI_UJSONTYPE_REQ1', 'INT_VALUE', 1, 9001, 9000, 'INT 타입 필드', 2203, 2102, NULL, 5, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'Integer', 0, NULL, NULL), + ('EAI_UJSONTYPE_REQ1', 'LONG_VALUE', 2, 9002, 9000, 'LONG 타입 필드', 2203, 2103, NULL, 10, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'Long', 0, NULL, NULL), + ('EAI_UJSONTYPE_REQ1', 'BIG_VALUE', 3, 9003, 9000, 'BIGDECIMAL length=10 decimal=5', 2203, 2118, NULL, 10, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 5, 'BigDecimal', 0, NULL, NULL), + ('EAI_UJSONTYPE_REQ1', 'BIG15_VALUE', 4, 9004, 9000, 'BIGDECIMAL length=15 decimal=0', 2203, 2118, NULL, 15, NULL, NULL, NULL, 1, 1, NULL, 'N', 2, 0, 'BigDecimal', 0, NULL, NULL);