package cn.iocoder.yudao.module.iot.core.util; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.topic.event.IotDeviceEventPostReqDTO; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import java.util.Set; import static org.junit.jupiter.api.Assertions.*; /** * {@link IotDeviceMessageUtils} 的单元测试 * * @author HUIHUI */ public class IotDeviceMessageUtilsTest { @Test public void testExtractPropertyValue_directValue() { // 测试直接值(非 Map) IotDeviceMessage message = new IotDeviceMessage(); message.setParams(25.5); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_directIdentifier() { // 测试直接通过标识符获取 IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("temperature", 25.5); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_propertiesStructure() { // 测试 properties 结构 IotDeviceMessage message = new IotDeviceMessage(); Map properties = new HashMap<>(); properties.put("temperature", 25.5); properties.put("humidity", 60); Map params = new HashMap<>(); params.put("properties", properties); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_dataStructure() { // 测试 data 结构 IotDeviceMessage message = new IotDeviceMessage(); Map data = new HashMap<>(); data.put("temperature", 25.5); Map params = new HashMap<>(); params.put("data", data); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_valueField() { // 测试 value 字段(策略 5) IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("identifier", "temperature"); params.put("value", 25.5); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_singleValueMap() { // 测试单值 Map(策略 6:包含 identifier 和一个其他字段) IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("identifier", "temperature"); params.put("actualValue", 25.5); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); } @Test public void testExtractPropertyValue_notFound() { // 测试未找到属性值 IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("humidity", 60); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertNull(result); } @Test public void testExtractPropertyValue_nullParams() { // 测试 params 为 null IotDeviceMessage message = new IotDeviceMessage(); message.setParams(null); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertNull(result); } @Test public void testExtractPropertyValue_priorityOrder() { // 测试优先级顺序:直接标识符 > properties > data > value IotDeviceMessage message = new IotDeviceMessage(); Map properties = new HashMap<>(); properties.put("temperature", 20.0); Map data = new HashMap<>(); data.put("temperature", 30.0); Map params = new HashMap<>(); params.put("temperature", 25.5); // 最高优先级 params.put("properties", properties); params.put("data", data); params.put("value", 40.0); message.setParams(params); Object result = IotDeviceMessageUtils.extractPropertyValue(message, "temperature"); assertEquals(25.5, result); // 应该返回直接标识符的值 } // ========== extractEventValue 测试 ========== @Test public void testExtractEventValue_scalar() { // 标量事件值:{identifier: "gzzt", value: "normal"} IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("identifier", "gzzt"); params.put("value", "normal"); message.setParams(params); Object result = IotDeviceMessageUtils.extractEventValue(message); assertEquals("normal", result); } @Test public void testExtractEventValue_struct() { // 结构体事件值:{identifier: "alarm", value: {level: "high", message: "..."}} IotDeviceMessage message = new IotDeviceMessage(); Map eventValue = new HashMap<>(); eventValue.put("level", "high"); eventValue.put("message", "over temperature"); Map params = new HashMap<>(); params.put("identifier", "alarm"); params.put("value", eventValue); message.setParams(params); Object result = IotDeviceMessageUtils.extractEventValue(message); assertEquals(eventValue, result); } @Test public void testExtractEventValue_nullParams() { IotDeviceMessage message = new IotDeviceMessage(); message.setParams(null); Object result = IotDeviceMessageUtils.extractEventValue(message); assertNull(result); } @Test public void testExtractEventValue_paramsWithoutValueField() { // params 是字符串等非结构化对象,无 value 字段,应返回 null IotDeviceMessage message = new IotDeviceMessage(); message.setParams("not a map"); Object result = IotDeviceMessageUtils.extractEventValue(message); assertNull(result); } @Test public void testExtractEventValue_missingValueField() { IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("identifier", "gzzt"); message.setParams(params); Object result = IotDeviceMessageUtils.extractEventValue(message); assertNull(result); } @Test public void testExtractEventValue_pojoParams() { // 本地总线场景:params 是 IotDeviceEventPostReqDTO POJO(未经 JSON 反序列化),应能反射取到 value IotDeviceMessage message = new IotDeviceMessage(); message.setParams(IotDeviceEventPostReqDTO.of("gzzt", "normal")); Object result = IotDeviceMessageUtils.extractEventValue(message); assertEquals("normal", result); } @Test public void testGetIdentifier_eventPostPojoParams() { // 本地总线场景:EVENT_POST 消息 params 是 DTO POJO,仍应能解析出 identifier IotDeviceMessage message = new IotDeviceMessage(); message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod()); message.setParams(IotDeviceEventPostReqDTO.of("gzzt", "normal")); assertEquals("gzzt", IotDeviceMessageUtils.getIdentifier(message)); } // ========== notContainsIdentifier 测试 ========== /** * 测试 notContainsIdentifier 与 containsIdentifier 的互补性 * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性** * **Validates: Requirements 4.1** */ @Test public void testNotContainsIdentifier_complementary_whenContains() { // 准备参数:消息包含指定标识符 IotDeviceMessage message = new IotDeviceMessage(); message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); Map params = new HashMap<>(); params.put("temperature", 25); message.setParams(params); String identifier = "temperature"; // 调用 & 断言:验证互补性 boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier); boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier); assertTrue(containsResult); assertFalse(notContainsResult); assertEquals(!containsResult, notContainsResult); } /** * 测试 notContainsIdentifier 与 containsIdentifier 的互补性 * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性** * **Validates: Requirements 4.1** */ @Test public void testNotContainsIdentifier_complementary_whenNotContains() { // 准备参数:消息不包含指定标识符 IotDeviceMessage message = new IotDeviceMessage(); message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); Map params = new HashMap<>(); params.put("temperature", 25); message.setParams(params); String identifier = "humidity"; // 调用 & 断言:验证互补性 boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier); boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier); assertFalse(containsResult); assertTrue(notContainsResult); assertEquals(!containsResult, notContainsResult); } /** * 测试 notContainsIdentifier 与 containsIdentifier 的互补性 - 空参数场景 * **Property 2: notContainsIdentifier 与 containsIdentifier 互补性** * **Validates: Requirements 4.1** */ @Test public void testNotContainsIdentifier_complementary_nullParams() { // 准备参数:params 为 null IotDeviceMessage message = new IotDeviceMessage(); message.setParams(null); String identifier = "temperature"; // 调用 & 断言:验证互补性 boolean containsResult = IotDeviceMessageUtils.containsIdentifier(message, identifier); boolean notContainsResult = IotDeviceMessageUtils.notContainsIdentifier(message, identifier); assertFalse(containsResult); assertTrue(notContainsResult); assertEquals(!containsResult, notContainsResult); } // ========== getPropertyIdentifiers 测试 ========== @Test public void testGetPropertyIdentifiers_flatStructure() { // 扁平结构:顶层 key 即标识符 IotDeviceMessage message = new IotDeviceMessage(); Map params = new HashMap<>(); params.put("temperature", 25.5); params.put("humidity", 60); message.setParams(params); Set identifiers = IotDeviceMessageUtils.getPropertyIdentifiers(message); assertEquals(2, identifiers.size()); assertTrue(identifiers.contains("temperature")); assertTrue(identifiers.contains("humidity")); } @Test public void testGetPropertyIdentifiers_nullMessage() { // 入参为 null:返回空集合 Set identifiers = IotDeviceMessageUtils.getPropertyIdentifiers(null); assertNotNull(identifiers); assertTrue(identifiers.isEmpty()); } @Test public void testGetPropertyIdentifiers_nullParams() { // params 为 null:返回空集合 IotDeviceMessage message = new IotDeviceMessage(); message.setParams(null); Set identifiers = IotDeviceMessageUtils.getPropertyIdentifiers(message); assertTrue(identifiers.isEmpty()); } @Test public void testGetPropertyIdentifiers_emptyParams() { // params 为空 Map:返回空集合 IotDeviceMessage message = new IotDeviceMessage(); message.setParams(new HashMap<>()); Set identifiers = IotDeviceMessageUtils.getPropertyIdentifiers(message); assertTrue(identifiers.isEmpty()); } @Test public void testGetPropertyIdentifiers_jsonStringParams() { // params 为 JSON 字符串:parseParamsToMap 解析后正常提取顶层标识符 IotDeviceMessage message = new IotDeviceMessage(); message.setParams("{\"temperature\":25.5,\"humidity\":60}"); Set identifiers = IotDeviceMessageUtils.getPropertyIdentifiers(message); assertEquals(2, identifiers.size()); assertTrue(identifiers.contains("temperature")); assertTrue(identifiers.contains("humidity")); } }