测试类

This commit is contained in:
yuejiajun 2025-09-28 16:52:57 +08:00
parent 11586563a7
commit 10a6da719f
2 changed files with 155 additions and 43 deletions

View File

@ -1484,18 +1484,45 @@ public class FormatUtil {
/** /**
* 格式化单个键 * 格式化单个键
*
* 根据指定的格式类型对键名进行格式化转换支持多种命名风格之间的转换
*
* <p><b>支持的格式类型</b></p>
* <ul>
* <li><b>uppercase</b> - 转换为全大写"userName" "USERNAME"</li>
* <li><b>lowercase</b> - 转换为全小写"UserName" "username"</li>
* <li><b>camelcase</b><b>snake_to_camel</b><b>snake_to_camel_lower</b> - 转换为小驼峰命名"user_name" "userName"</li>
* <li><b>snakecase</b> - 转换为蛇形命名"userName" "user_name"</li>
* <li><b>kebabcase</b> - 转换为短横线命名"userName" "user-name"</li>
* </ul>
*
* <p><b>转换规则说明</b></p>
* <ul>
* <li>未匹配到有效格式类型时返回原始键名</li>
* <li>格式类型匹配时不区分大小写"UpperCase""uppercase"效果一致</li>
* <li>驼峰转换会自动处理下划线短横线等分隔符"user-age" "userAge"</li>
* </ul>
*
* @param key 原始键名字符串可为null或空字符串
* @param format 格式类型字符串指定目标命名风格
* @return 格式化后的键名若原始键名为null则返回null
*/ */
private static String formatKey(String key, String format) { private static String formatKey(String key, String format) {
switch (format.toLowerCase()) { switch (format.toLowerCase()) {
case "uppercase": case "uppercase":
// 转换为全大写"userName" "USERNAME"
return key.toUpperCase(); return key.toUpperCase();
case "lowercase": case "lowercase":
// 转换为全小写"UserName" "username"
return key.toLowerCase(); return key.toLowerCase();
case "camelcase": case "camelcase":
// 转换为小驼峰命名"user_name" "userName"
return toCamelCase(key); return toCamelCase(key);
case "snakecase": case "snakecase":
// 转换为蛇形命名"userName" "user_name"
return toSnakeCase(key); return toSnakeCase(key);
case "kebabcase": case "kebabcase":
// 转换为短横线命名"userName" "user-name"
return toKebabCase(key); return toKebabCase(key);
default: default:
return key; return key;
@ -1527,7 +1554,10 @@ public class FormatUtil {
private static String toSnakeCase(String str) { private static String toSnakeCase(String str) {
if (str == null || str.isEmpty()) return str; if (str == null || str.isEmpty()) return str;
return str.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase(); String processResult = str.replaceAll("-+", "_");
processResult = processResult.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
processResult = processResult.replaceAll("([a-zA-Z0-9]+)(_+([a-zA-Z0-9]+))+", "$1_$3").toLowerCase();
return processResult;
} }
/** /**
@ -1536,7 +1566,8 @@ public class FormatUtil {
private static String toKebabCase(String str) { private static String toKebabCase(String str) {
if (str == null || str.isEmpty()) return str; if (str == null || str.isEmpty()) return str;
return str.replaceAll("([a-z])([A-Z])", "$1-$2").toLowerCase(); String processResult = str.replaceAll("_+", "-");
return processResult.replaceAll("([a-z])([A-Z])", "$1-$2").toLowerCase();
} }
/** /**

View File

@ -448,7 +448,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回空字符串或错误信息</p> * <p><b>预计结果</b>返回空字符串或错误信息</p>
*/ */
@Test @Test
@DisplayName("substring - 起始位置超界") @DisplayName("substring - 起始位置超界 - 【验证中】")
void testSubstring_StartOutOfBounds() { void testSubstring_StartOutOfBounds() {
System.out.println(); System.out.println();
log.info("========== 字符串截取模块测试 - 起始位置超界 =========="); log.info("========== 字符串截取模块测试 - 起始位置超界 ==========");
@ -713,16 +713,13 @@ public class FormatUtilTest {
replacementMap.put("Hello", "Hi"); replacementMap.put("Hello", "Hi");
replacementMap.put("world", "universe"); replacementMap.put("world", "universe");
boolean caseSensitive = true; boolean caseSensitive = true;
log.info("输入参数:"); log.info("输入参数:");
log.info(" - 输入字符串: {}", inputString); log.info(" - 输入字符串: {}", inputString);
log.info(" - 替换映射: {}", JSON.toJSONString(replacementMap)); log.info(" - 替换映射: {}", JSON.toJSONString(replacementMap));
log.info(" - 大小写敏感: {}", caseSensitive); log.info(" - 大小写敏感: {}", caseSensitive);
log.info(" - 注意: 'Hello'与'hello'大小写不匹配"); log.info(" - 注意: 'Hello'与'hello'大小写不匹配");
// 执行测试 // 执行测试
String result = FormatUtil.stealBeamsAndReplacePillars(inputString, replacementMap, caseSensitive); String result = FormatUtil.stealBeamsAndReplacePillars(inputString, replacementMap, caseSensitive);
// 断言验证 // 断言验证
String expectedResult = "hello universe"; String expectedResult = "hello universe";
log.info("预期结果:'{}'", expectedResult); log.info("预期结果:'{}'", expectedResult);
@ -792,24 +789,19 @@ public class FormatUtilTest {
String coordinate = "116°23'45.67\""; String coordinate = "116°23'45.67\"";
params.put("fromType", "dms"); params.put("fromType", "dms");
params.put("toType", "decimal"); params.put("toType", "decimal");
log.info("输入参数:"); log.info("输入参数:");
log.info(" - 坐标值: {}", coordinate); log.info(" - 坐标值: {}", coordinate);
log.info(" - 源格式: {}", params.get("fromType")); log.info(" - 源格式: {}", params.get("fromType"));
log.info(" - 目标格式: {}", params.get("toType")); log.info(" - 目标格式: {}", params.get("toType"));
log.info(" - 注意: 116°23'45.67\" ≈ 116.396019"); log.info(" - 注意: 116°23'45.67\" ≈ 116.396019");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试 // 执行测试
Object result = FormatUtil.coordinateConvert(coordinate, params); Object result = FormatUtil.coordinateConvert(coordinate, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证 // 断言验证
assertNotNull(result); String expectedResult = "116.396019";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 度分秒转十进制转换正确"); log.info("✓ 测试通过 - 度分秒转十进制转换正确");
} }
@ -974,7 +966,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回最大值</p> * <p><b>预计结果</b>返回最大值</p>
*/ */
@Test @Test
@DisplayName("boundaryCheck - 超出上限截断") @DisplayName("boundaryCheck - 超出上限截断 - 【验证中】")
void testBoundaryCheck_AboveMaxTruncate() { void testBoundaryCheck_AboveMaxTruncate() {
System.out.println(); System.out.println();
log.info("========== 极值检查模块测试 - 超出上限截断处理 =========="); log.info("========== 极值检查模块测试 - 超出上限截断处理 ==========");
@ -1100,34 +1092,128 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p> * <p><b>预计结果</b>转换结果正确</p>
*/ */
@Test @Test
@DisplayName("kvMapping - 键名格式转换 - 【验证") @DisplayName("kvMapping - 键名格式转换 - 【验证】")
void testKvMapping_KeyFormatConversion() { void testKvMapping_KeyFormatConversion() {
System.out.println(); System.out.println();
log.info("========== 数据KV映射模块测试 - 键名格式转换 =========="); log.info("========== 数据KV映射模块测试 - 键名格式转换 ==========");
// 输入参数 // 输入参数
Map<String, Object> inputMap = new HashMap<>(); Map<String, Object> inputMap = new HashMap<>();
inputMap.put("user_name", "张三");
inputMap.put("user_age", 25); // =================== 全大写命名 ===================
params.put("keyFormat", "snake_to_camel"); inputMap.put("USER_ID", 1001);
inputMap.put("STATUS", "ACTIVE");
// =================== 全小写命名 ===================
inputMap.put("name", "李四");
inputMap.put("address", "北京市朝阳区");
inputMap.put("phone", "13800138000");
// =================== 小驼峰命名 (lowerCamelCase) ===================
inputMap.put("userName", "王五");
// =================== 大驼峰命名 (UpperCamelCase/PascalCase) ===================
inputMap.put("UserRole", "ADMIN");
// =================== 蛇形命名 (snake_case) ===================
inputMap.put("user_password", "encrypted123");
// =================== 短横线命名 (kebab-case) ===================
inputMap.put("user-address", "上海市浦东新区");
// 1. 转成全大写
System.out.println();
log.info("========== 转成全大写 ==========");
params.put("keyFormat", "uppercase");
log.info("输入参数:"); log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap); log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat")); log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 蛇形命名(user_name)转驼峰命名(userName)"); log.info(" - 注意: 短横杠在全大写中,不做处理");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试 // 执行测试
Object result = FormatUtil.kvMapping(inputMap, params); Object result = FormatUtil.kvMapping(inputMap, params);
// 实际结果 // 断言验证
Map<String, Object> expectedResult = new HashMap<>(); String expectedResultString = """
expectedResult.put("userName", "张三"); {"USERROLE":"ADMIN","STATUS":"ACTIVE","USER-ADDRESS":"上海市浦东新区","USER_PASSWORD":"encrypted123","ADDRESS":"北京市朝阳区","PHONE":"13800138000","USER_ID":1001,"USERNAME":"王五","NAME":"李四"}
expectedResult.put("userAge", 25); """.trim();
String expectedResultString = JSON.toJSONString(expectedResult);
String resultString = JSON.toJSONString(result); String resultString = JSON.toJSONString(result);
log.info("预期结果: {}", expectedResultString); log.info("预期结果: {}", expectedResultString);
log.info("实际结果: {}", resultString); log.info("实际结果: {}", resultString);
assertEquals(expectedResultString, resultString, String.format("转换为全大写%s失败", params.get("keyFormat")));
// 2. 转成全小写
System.out.println();
log.info("========== 转成全小写 ==========");
params.put("keyFormat", "lowercase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在全小写中,不做处理");
// 执行测试
Object result2 = FormatUtil.kvMapping(inputMap, params);
// 断言验证 // 断言验证
assertEquals(expectedResultString, resultString, "蛇形命名(user_name)转驼峰命名(userName) 失败"); String expectedResultString2 = """
{"user_password":"encrypted123","address":"北京市朝阳区","phone":"13800138000","user_id":1001,"name":"李四","userrole":"ADMIN","user-address":"上海市浦东新区","status":"ACTIVE","username":"王五"}
""".trim();
String resultString2 = JSON.toJSONString(result2);
log.info("预期结果: {}", expectedResultString2);
log.info("实际结果: {}", resultString2);
assertEquals(expectedResultString2, resultString2, String.format("转换为全小写%s失败", params.get("keyFormat")));
// 3. 转换为小驼峰命名
System.out.println();
log.info("========== 转换为小驼峰命名 ==========");
params.put("keyFormat", "camelcase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 所有值都被转为驼峰,不区分当前是否大小写,只判断 [ _ | - | ' '] 下划线、短横杠、空串三种。");
// 执行测试
Object result3 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString3 = """
{"userAddress":"上海市浦东新区","userPassword":"encrypted123","address":"北京市朝阳区","phone":"13800138000","name":"李四","userrole":"ADMIN","userId":1001,"status":"ACTIVE","username":"王五"}
""".trim();
String resultString3 = JSON.toJSONString(result3);
log.info("预期结果: {}", expectedResultString3);
log.info("实际结果: {}", resultString3);
assertEquals(expectedResultString3, resultString3, String.format("转换为小驼峰命名%s失败", params.get("keyFormat")));
// 4. 转换为蛇形命名
System.out.println();
log.info("========== 转换为蛇形命名 ==========");
params.put("keyFormat", "snakecase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在蛇形命名中,不做处理");
// 执行测试
Object result4 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString4 = """
{"user_role":"ADMIN","user_password":"encrypted123","address":"北京市朝阳区","phone":"13800138000","user_id":1001,"user_name":"王五","user_address":"上海市浦东新区","name":"李四","status":"ACTIVE"}
""".trim();
String resultString4 = JSON.toJSONString(result4);
log.info("预期结果: {}", expectedResultString4);
log.info("实际结果: {}", resultString4);
assertEquals(expectedResultString4, resultString4, String.format("转换为蛇形命名%s失败", params.get("keyFormat")));
// 5. 转换为短横线命名
System.out.println();
log.info("========== 转换为短横线命名 ==========");
params.put("keyFormat", "kebabcase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在全大写中,不做处理");
// 执行测试
Object result5 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString5 = """
{"user-password":"encrypted123","address":"北京市朝阳区","user-role":"ADMIN","user-name":"王五","phone":"13800138000","user-id":1001,"name":"李四","user-address":"上海市浦东新区","status":"ACTIVE"}
""".trim();
String resultString5 = JSON.toJSONString(result5);
log.info("预期结果: {}", expectedResultString5);
log.info("实际结果: {}", resultString5);
assertEquals(expectedResultString5, resultString5, String.format("转换为短横线命名%s失败", params.get("keyFormat")));
log.info("✓ 测试通过 - 键名格式转换正确"); log.info("✓ 测试通过 - 键名格式转换正确");
} }
@ -1271,7 +1357,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>组合处理结果正确</p> * <p><b>预计结果</b>组合处理结果正确</p>
*/ */
@Test @Test
@DisplayName("综合测试 - 多方法组合使用") @DisplayName("boundaryCheck - 综合测试 - 多方法组合使用 - 【验证中】")
void testMultipleMethods_CombinedUsage() { void testMultipleMethods_CombinedUsage() {
System.out.println(); System.out.println();
log.info("========== 综合测试 - 多方法组合使用 =========="); log.info("========== 综合测试 - 多方法组合使用 ==========");
@ -1334,7 +1420,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>所有转换正确完成</p> * <p><b>预计结果</b>所有转换正确完成</p>
*/ */
@Test @Test
@DisplayName("coordinateConvert - 性能测试 - 大量数据处理") @DisplayName("coordinateConvert - 性能测试 - 大量数据处理 - 【验证中】")
void testPerformance_LargeDataProcessing() { void testPerformance_LargeDataProcessing() {
System.out.println(); System.out.println();
log.info("========== 性能测试 - 大量数据处理 =========="); log.info("========== 性能测试 - 大量数据处理 ==========");
@ -1347,11 +1433,9 @@ public class FormatUtilTest {
log.info(" - 目标格式: decimal"); log.info(" - 目标格式: decimal");
log.info(" - 坐标模式: 116.0°23'45.67\" ~ 116.999°23'45.67\""); log.info(" - 坐标模式: 116.0°23'45.67\" ~ 116.999°23'45.67\"");
log.info(" - 性能要求: 处理时间 < 5000 ms"); log.info(" - 性能要求: 处理时间 < 5000 ms");
// 开始性能测试 // 开始性能测试
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
log.info("开始性能测试..."); log.info("开始性能测试...");
for (int i = 0; i < testCount; i++) { for (int i = 0; i < testCount; i++) {
Map<String, Object> coordParams = new HashMap<>(); Map<String, Object> coordParams = new HashMap<>();
coordParams.put("fromType", "dms"); coordParams.put("fromType", "dms");
@ -1360,22 +1444,19 @@ public class FormatUtilTest {
Object result = FormatUtil.coordinateConvert("116." + i + "°23'45.67\"", coordParams); Object result = FormatUtil.coordinateConvert("116." + i + "°23'45.67\"", coordParams);
assertNotNull(result); assertNotNull(result);
} }
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
long duration = endTime - startTime; long duration = endTime - startTime;
// 实际结果 // 实际结果
log.info("性能测试结果:"); log.info("性能测试结果:");
log.info(" - 开始时间: {} ms", startTime); log.info(" - 开始时间: {} ms", startTime);
log.info(" - 结束时间: {} ms", endTime); log.info(" - 结束时间: {} ms", endTime);
log.info(" - 总耗时: {} ms", duration); log.info(" - 总耗时: {} ms", duration);
log.info(" - 平均每个转换耗时: {} ms", (double)duration / testCount); log.info(" - 平均每个转换耗时: {} ms", (double)duration / testCount);
// 预期结果 // 预期结果
log.info("预期结果: 处理时间 < 5000 ms"); log.info("预期结果: 处理时间 < 100 ms");
// 断言验证 // 断言验证
assertTrue(duration < 5000, "性能测试应在5秒内完成"); assertTrue(duration < 100, "性能测试应在0.1秒内完成");
log.info("✓ 测试通过 - 性能表现符合要求"); log.info("✓ 测试通过 - 性能表现符合要求");
} }
@ -1420,7 +1501,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>正确处理或返回错误信息</p> * <p><b>预计结果</b>正确处理或返回错误信息</p>
*/ */
@Test @Test
@DisplayName("边界值测试 - 极值输入") @DisplayName("boundaryCheck - 边界值测试 - 极值输入 - 【验证中】")
void testBoundaryValues_ExtremeInputs() { void testBoundaryValues_ExtremeInputs() {
System.out.println(); System.out.println();
log.info("========== 边界值测试 - 极值输入 =========="); log.info("========== 边界值测试 - 极值输入 ==========");