!1413 场景联动优化 review 提到的逻辑

Merge pull request !1413 from puhui999/feature/iot
This commit is contained in:
芋道源码 2025-08-24 09:22:46 +00:00 committed by Gitee
commit 21945e6b1e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
21 changed files with 1243 additions and 1042 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.iot.enums.rule;
import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ -32,4 +33,8 @@ public enum IotSceneRuleConditionTypeEnum implements ArrayValuable<Integer> {
return ARRAYS;
}
public static IotSceneRuleConditionTypeEnum typeOf(Integer type) {
return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
}
}

View File

@ -55,9 +55,8 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
@Resource
private IotDeviceService deviceService;
// TODO @puhui999sceneRuleMatcherManager 变量名
@Resource
private IotSceneRuleMatcherManager matcherManager;
private IotSceneRuleMatcherManager sceneRuleMatcherManager;
@Resource
private List<IotSceneRuleAction> sceneRuleActions;
@ -275,7 +274,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
private boolean matchSingleTrigger(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, IotSceneRuleDO sceneRule) {
try {
// 2. 检查触发器的条件分组
return matcherManager.isMatched(message, trigger) && isTriggerConditionGroupsMatched(message, trigger, sceneRule);
return sceneRuleMatcherManager.isMatched(message, trigger) && isTriggerConditionGroupsMatched(message, trigger, sceneRule);
} catch (Exception e) {
log.error("[matchSingleTrigger][触发器匹配异常] sceneRuleId: {}, triggerType: {}, message: {}",
sceneRule.getId(), trigger.getType(), message, e);
@ -334,7 +333,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) {
try {
return matcherManager.isConditionMatched(message, condition);
return sceneRuleMatcherManager.isConditionMatched(message, condition);
} catch (Exception e) {
log.error("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 条件匹配异常]",
sceneRule.getId(), trigger, e);

View File

@ -12,7 +12,6 @@ import org.springframework.stereotype.Component;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@ -37,33 +36,26 @@ public class IotSceneRuleMatcherManager {
*/
private final Map<IotSceneRuleConditionTypeEnum, IotSceneRuleConditionMatcher> conditionMatchers;
/**
* 所有匹配器列表按优先级排序
*/
// TODO @puhui999貌似 local variable 也可以
private final List<IotSceneRuleMatcher> allMatchers;
public IotSceneRuleMatcherManager(List<IotSceneRuleMatcher> matchers) {
if (CollUtil.isEmpty(matchers)) {
log.warn("[IotSceneRuleMatcherManager][没有找到任何匹配器]");
this.triggerMatchers = new HashMap<>();
this.conditionMatchers = new HashMap<>();
this.allMatchers = new ArrayList<>();
return;
}
// 按优先级排序并过滤启用的匹配器
this.allMatchers = matchers.stream()
List<IotSceneRuleMatcher> allMatchers = matchers.stream()
.filter(IotSceneRuleMatcher::isEnabled)
.sorted(Comparator.comparing(IotSceneRuleMatcher::getPriority))
.collect(Collectors.toList());
.toList();
// 分离触发器匹配器和条件匹配器
List<IotSceneRuleTriggerMatcher> triggerMatchers = this.allMatchers.stream()
List<IotSceneRuleTriggerMatcher> triggerMatchers = allMatchers.stream()
.filter(matcher -> matcher instanceof IotSceneRuleTriggerMatcher)
.map(matcher -> (IotSceneRuleTriggerMatcher) matcher)
.toList();
List<IotSceneRuleConditionMatcher> conditionMatchers = this.allMatchers.stream()
List<IotSceneRuleConditionMatcher> conditionMatchers = allMatchers.stream()
.filter(matcher -> matcher instanceof IotSceneRuleConditionMatcher)
.map(matcher -> (IotSceneRuleConditionMatcher) matcher)
.toList();
@ -92,7 +84,7 @@ public class IotSceneRuleMatcherManager {
// 日志输出初始化信息
log.info("[IotSceneRuleMatcherManager][初始化完成,共加载({})个匹配器,其中触发器匹配器({})个,条件匹配器({})个]",
this.allMatchers.size(), this.triggerMatchers.size(), this.conditionMatchers.size());
allMatchers.size(), this.triggerMatchers.size(), this.conditionMatchers.size());
this.triggerMatchers.forEach((type, matcher) ->
log.info("[IotSceneRuleMatcherManager][触发器匹配器类型: ({}), 优先级: ({})] ", type, matcher.getPriority()));
this.conditionMatchers.forEach((type, matcher) ->
@ -123,7 +115,7 @@ public class IotSceneRuleMatcherManager {
}
try {
return matcher.isMatched(message, trigger);
return matcher.matches(message, trigger);
} catch (Exception e) {
log.error("[isMatched][触发器匹配异常] message: {}, trigger: {}", message, trigger, e);
return false;
@ -144,7 +136,7 @@ public class IotSceneRuleMatcherManager {
}
// 根据条件类型查找对应的匹配器
IotSceneRuleConditionTypeEnum conditionType = findConditionTypeEnum(condition.getType());
IotSceneRuleConditionTypeEnum conditionType = IotSceneRuleConditionTypeEnum.typeOf(condition.getType());
if (conditionType == null) {
log.warn("[isConditionMatched][conditionType({}) 未知的条件类型]", condition.getType());
return false;
@ -157,45 +149,11 @@ public class IotSceneRuleMatcherManager {
// 执行匹配逻辑
try {
return matcher.isMatched(message, condition);
return matcher.matches(message, condition);
} catch (Exception e) {
log.error("[isConditionMatched][message({}) condition({}) 条件匹配异常]", message, condition, e);
return false;
}
}
/**
* 根据类型值查找条件类型枚举
*
* @param typeValue 类型值
* @return 条件类型枚举
*/
private IotSceneRuleConditionTypeEnum findConditionTypeEnum(Integer typeValue) {
// TODO @puhui999是不是搞到枚举类里
return Arrays.stream(IotSceneRuleConditionTypeEnum.values())
.filter(type -> type.getType().equals(typeValue))
.findFirst()
.orElse(null);
}
// TODO @puhui999下面两个方法是不是也可以删除哈
/**
* 获取所有支持的触发器类型
*
* @return 支持的触发器类型列表
*/
public Set<IotSceneRuleTriggerTypeEnum> getSupportedTriggerTypes() {
return new HashSet<>(triggerMatchers.keySet());
}
/**
* 获取所有支持的条件类型
*
* @return 支持的条件类型列表
*/
public Set<IotSceneRuleConditionTypeEnum> getSupportedConditionTypes() {
return new HashSet<>(conditionMatchers.keySet());
}
}

View File

@ -43,7 +43,7 @@ public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效");
@ -123,7 +123,6 @@ public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher
isDateTimeOperator(operatorEnum);
}
// TODO @puhui999switch 兼容下 jdk8
/**
* 匹配日期时间时间戳
* 直接实现时间戳比较逻辑
@ -131,15 +130,17 @@ public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher
private boolean matchDateTime(long currentTimestamp, IotSceneRuleConditionOperatorEnum operatorEnum, String param) {
try {
long targetTimestamp = Long.parseLong(param);
return switch (operatorEnum) {
case DATE_TIME_GREATER_THAN -> currentTimestamp > targetTimestamp;
case DATE_TIME_LESS_THAN -> currentTimestamp < targetTimestamp;
case DATE_TIME_BETWEEN -> matchDateTimeBetween(currentTimestamp, param);
default -> {
switch (operatorEnum) {
case DATE_TIME_GREATER_THAN:
return currentTimestamp > targetTimestamp;
case DATE_TIME_LESS_THAN:
return currentTimestamp < targetTimestamp;
case DATE_TIME_BETWEEN:
return matchDateTimeBetween(currentTimestamp, param);
default:
log.warn("[matchDateTime][operatorEnum({}) 不支持的日期时间操作符]", operatorEnum);
yield false;
}
};
return false;
}
} catch (Exception e) {
log.error("[matchDateTime][operatorEnum({}) param({}) 日期时间匹配异常]", operatorEnum, param, e);
return false;
@ -167,15 +168,17 @@ public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher
private boolean matchTime(LocalTime currentTime, IotSceneRuleConditionOperatorEnum operatorEnum, String param) {
try {
LocalTime targetTime = parseTime(param);
return switch (operatorEnum) {
case TIME_GREATER_THAN -> currentTime.isAfter(targetTime);
case TIME_LESS_THAN -> currentTime.isBefore(targetTime);
case TIME_BETWEEN -> matchTimeBetween(currentTime, param);
default -> {
switch (operatorEnum) {
case TIME_GREATER_THAN:
return currentTime.isAfter(targetTime);
case TIME_LESS_THAN:
return currentTime.isBefore(targetTime);
case TIME_BETWEEN:
return matchTimeBetween(currentTime, param);
default:
log.warn("[matchTime][operatorEnum({}) 不支持的时间操作符]", operatorEnum);
yield false;
}
};
return false;
}
} catch (Exception e) {
log.error("[matchTime][][operatorEnum({}) param({}) 时间解析异常]", operatorEnum, param, e);
return false;

View File

@ -22,9 +22,8 @@ public class DevicePropertyConditionMatcher implements IotSceneRuleConditionMatc
return IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY;
}
// TODO @puhui999matches 会不会更好参考的 org.hamcrest.Matcher jdk 接口
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效");

View File

@ -22,7 +22,7 @@ public class DeviceStateConditionMatcher implements IotSceneRuleConditionMatcher
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicConditionValid(condition)) {
IotSceneRuleMatcherHelper.logConditionMatchFailure(message, condition, "条件基础参数无效");

View File

@ -33,6 +33,6 @@ public interface IotSceneRuleConditionMatcher extends IotSceneRuleMatcher {
* @param condition 触发条件
* @return 是否匹配
*/
boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition);
boolean matches(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition);
}

View File

@ -25,7 +25,7 @@ public class DeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatcher
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");

View File

@ -24,7 +24,7 @@ public class DevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerMatc
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");

View File

@ -24,7 +24,7 @@ public class DeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMat
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");

View File

@ -23,7 +23,7 @@ public class DeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatch
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");

View File

@ -33,6 +33,6 @@ public interface IotSceneRuleTriggerMatcher extends IotSceneRuleMatcher {
* @param trigger 触发器配置
* @return 是否匹配
*/
boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger);
boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger);
}

View File

@ -25,7 +25,7 @@ public class TimerTriggerMatcher implements IotSceneRuleTriggerMatcher {
}
@Override
public boolean isMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
public boolean matches(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
// 1.1 基础参数校验
if (!IotSceneRuleMatcherHelper.isBasicTriggerValid(trigger)) {
IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");

View File

@ -5,103 +5,110 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link CurrentTimeConditionMatcher} 的单元测试
* {@link CurrentTimeConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private CurrentTimeConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new CurrentTimeConditionMatcher();
}
@Test
public void testGetSupportedConditionType() {
// when & then
assertEquals(IotSceneRuleConditionTypeEnum.CURRENT_TIME, matcher.getSupportedConditionType());
// 调用
IotSceneRuleConditionTypeEnum result = matcher.getSupportedConditionType();
// 断言
assertEquals(IotSceneRuleConditionTypeEnum.CURRENT_TIME, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(40, matcher.getPriority());
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(40, result);
}
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
// 调用
boolean result = matcher.isEnabled();
// 断言
assertTrue(result);
}
// ========== 时间戳条件测试 ==========
@Test
public void testIsMatched_DateTimeGreaterThan_Success() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_DateTimeGreaterThan_success() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
long pastTimestamp = LocalDateTime.now().minusHours(1).toEpochSecond(ZoneOffset.of("+8"));
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
String.valueOf(pastTimestamp)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_DateTimeGreaterThan_Failure() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_DateTimeGreaterThan_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
long futureTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
String.valueOf(futureTimestamp)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_DateTimeLessThan_Success() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_DateTimeLessThan_success() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
long futureTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
IotSceneRuleConditionOperatorEnum.DATE_TIME_LESS_THAN.getOperator(),
String.valueOf(futureTimestamp)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_DateTimeBetween_Success() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_DateTimeBetween_success() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
long startTimestamp = LocalDateTime.now().minusHours(1).toEpochSecond(ZoneOffset.of("+8"));
long endTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
@ -109,17 +116,17 @@ public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
startTimestamp + "," + endTimestamp
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_DateTimeBetween_Failure() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_DateTimeBetween_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
long startTimestamp = LocalDateTime.now().plusHours(1).toEpochSecond(ZoneOffset.of("+8"));
long endTimestamp = LocalDateTime.now().plusHours(2).toEpochSecond(ZoneOffset.of("+8"));
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
@ -127,78 +134,78 @@ public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
startTimestamp + "," + endTimestamp
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
// ========== 当日时间条件测试 ==========
@Test
public void testIsMatched_TimeGreaterThan_EarlyMorning() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_TimeGreaterThan_earlyMorning() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_GREATER_THAN.getOperator(),
"06:00:00" // 早上6点
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
// 结果取决于当前时间如果当前时间大于6点则为true
assertNotNull(result);
}
@Test
public void testIsMatched_TimeLessThan_LateNight() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_TimeLessThan_lateNight() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_LESS_THAN.getOperator(),
"23:59:59" // 晚上11点59分59秒
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
// 大部分情况下应该为true除非在午夜前1秒运行测试
assertNotNull(result);
}
@Test
public void testIsMatched_TimeBetween_AllDay() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_TimeBetween_allDay() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
"00:00:00,23:59:59" // 全天
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result); // 全天范围应该总是匹配
}
@Test
public void testIsMatched_TimeBetween_WorkingHours() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_TimeBetween_workingHours() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
"09:00:00,17:00:00" // 工作时间
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
// 结果取决于当前时间是否在工作时间内
assertNotNull(result);
}
@ -206,97 +213,106 @@ public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
// ========== 异常情况测试 ==========
@Test
public void testIsMatched_NullCondition() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_nullCondition() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_NullConditionType() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_nullConditionType() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(null);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_InvalidOperator() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_invalidOperator() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(IotSceneRuleConditionTypeEnum.CURRENT_TIME.getType());
condition.setOperator("invalid_operator");
condition.setOperator(randomString()); // 随机无效操作符
condition.setParam("12:00:00");
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_InvalidTimeFormat() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_invalidTimeFormat() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_GREATER_THAN.getOperator(),
"invalid-time-format"
randomString() // 随机无效时间格式
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_InvalidTimestampFormat() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_invalidTimestampFormat() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createDateTimeCondition(
IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN.getOperator(),
"invalid-timestamp"
randomString() // 随机无效时间戳格式
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_InvalidBetweenFormat() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_invalidBetweenFormat() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.TriggerCondition condition = createTimeCondition(
IotSceneRuleConditionOperatorEnum.TIME_BETWEEN.getOperator(),
"09:00:00" // 缺少结束时间
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
// ========== 辅助方法 ==========
/**
* 创建设备消息
*/
private IotDeviceMessage createDeviceMessage() {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
return message;
}
/**
* 创建日期时间条件
*/
@ -318,4 +334,5 @@ public class CurrentTimeConditionMatcherTest extends BaseMockitoUnitTest {
condition.setParam(param);
return condition;
}
}

View File

@ -6,185 +6,206 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import java.util.HashMap;
import java.util.Map;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DevicePropertyConditionMatcher} 的单元测试
* {@link DevicePropertyConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DevicePropertyConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DevicePropertyConditionMatcher();
}
@Test
public void testGetSupportedConditionType() {
// when & then
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY, matcher.getSupportedConditionType());
// 调用
IotSceneRuleConditionTypeEnum result = matcher.getSupportedConditionType();
// 断言
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(20, matcher.getPriority());
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(20, result);
}
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
// 调用
boolean result = matcher.isEnabled();
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_TemperatureEquals() {
// given
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
public void testMatches_temperatureEquals_success() {
// 准备参数
String propertyName = "temperature";
Double propertyValue = 25.5;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"25.5"
String.valueOf(propertyValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_HumidityGreaterThan() {
// given
Map<String, Object> properties = MapUtil.of("humidity", 75);
public void testMatches_humidityGreaterThan_success() {
// 准备参数
String propertyName = "humidity";
Integer propertyValue = 75;
Integer compareValue = 70;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"humidity",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"70"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_PressureLessThan() {
// given
Map<String, Object> properties = MapUtil.of("pressure", 1010.5);
public void testMatches_pressureLessThan_success() {
// 准备参数
String propertyName = "pressure";
Double propertyValue = 1010.5;
Integer compareValue = 1020;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"pressure",
propertyName,
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
"1020"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_StatusNotEquals() {
// given
Map<String, Object> properties = MapUtil.of("status", "active");
public void testMatches_statusNotEquals_success() {
// 准备参数
String propertyName = "status";
String propertyValue = "active";
String compareValue = "inactive";
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"status",
propertyName,
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
"inactive"
compareValue
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_PropertyMismatch() {
// given
Map<String, Object> properties = MapUtil.of("temperature", 15.0);
public void testMatches_propertyMismatch_fail() {
// 准备参数
String propertyName = "temperature";
Double propertyValue = 15.0;
Integer compareValue = 20;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_PropertyNotFound() {
// given
public void testMatches_propertyNotFound_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"humidity", // 不存在的属性
randomString(), // 随机不存在的属性
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"50"
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullCondition() {
// given
public void testMatches_nullCondition_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullConditionType() {
// given
public void testMatches_nullConditionType_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(null);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingIdentifier() {
// given
public void testMatches_missingIdentifier_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
@ -193,16 +214,16 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
condition.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
condition.setParam("20");
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingOperator() {
// given
public void testMatches_missingOperator_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
@ -211,16 +232,16 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
condition.setOperator(null); // 缺少操作符
condition.setParam("20");
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingParam() {
// given
public void testMatches_missingParam_fail() {
// 准备参数
Map<String, Object> properties = MapUtil.of("temperature", 25.5);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
@ -229,123 +250,131 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
condition.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
condition.setParam(null); // 缺少参数
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessage() {
// given
public void testMatches_nullMessage_fail() {
// 准备参数
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"temperature",
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
);
// when
boolean result = matcher.isMatched(null, condition);
// 调用
boolean result = matcher.matches(null, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullDeviceProperties() {
// given
public void testMatches_nullDeviceProperties_fail() {
// 准备参数
IotDeviceMessage message = new IotDeviceMessage();
message.setParams(null);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"temperature",
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_GreaterThanOrEquals() {
// given
Map<String, Object> properties = MapUtil.of("voltage", 12.0);
public void testMatches_voltageGreaterThanOrEquals_success() {
// 准备参数
String propertyName = "voltage";
Double propertyValue = 12.0;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"voltage",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator(),
"12.0"
String.valueOf(propertyValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_LessThanOrEquals() {
// given
Map<String, Object> properties = MapUtil.of("current", 2.5);
public void testMatches_currentLessThanOrEquals_success() {
// 准备参数
String propertyName = "current";
Double propertyValue = 2.5;
Double compareValue = 3.0;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"current",
propertyName,
IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS.getOperator(),
"3.0"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_StringProperty() {
// given
Map<String, Object> properties = MapUtil.of("mode", "auto");
public void testMatches_stringProperty_success() {
// 准备参数
String propertyName = "mode";
String propertyValue = "auto";
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"mode",
propertyName,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"auto"
propertyValue
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_BooleanProperty() {
// given
Map<String, Object> properties = MapUtil.of("enabled", true);
public void testMatches_booleanProperty_success() {
// 准备参数
String propertyName = "enabled";
Boolean propertyValue = true;
Map<String, Object> properties = MapUtil.of(propertyName, propertyValue);
IotDeviceMessage message = createDeviceMessage(properties);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"enabled",
propertyName,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"true"
String.valueOf(propertyValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_MultipleProperties() {
// given
public void testMatches_multipleProperties_success() {
// 准备参数
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.put("humidity", 60)
@ -353,16 +382,18 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
.put("enabled", true)
.build();
IotDeviceMessage message = createDeviceMessage(properties);
String targetProperty = "humidity";
Integer targetValue = 60;
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
"humidity",
targetProperty,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"60"
String.valueOf(targetValue)
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@ -373,6 +404,7 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createDeviceMessage(Map<String, Object> properties) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setParams(properties);
return message;
}
@ -388,4 +420,5 @@ public class DevicePropertyConditionMatcherTest extends BaseMockitoUnitTest {
condition.setParam(param);
return condition;
}
}

View File

@ -6,307 +6,327 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceStateConditionMatcher} 的单元测试
* {@link DeviceStateConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceStateConditionMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DeviceStateConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceStateConditionMatcher();
}
@Test
public void testGetSupportedConditionType() {
// when & then
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_STATE, matcher.getSupportedConditionType());
// 调用
IotSceneRuleConditionTypeEnum result = matcher.getSupportedConditionType();
// 断言
assertEquals(IotSceneRuleConditionTypeEnum.DEVICE_STATE, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(30, matcher.getPriority());
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(30, result);
}
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
// 调用
boolean result = matcher.isEnabled();
@Test
public void testIsMatched_Success_OnlineState() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_OfflineState() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.OFFLINE.getState());
public void testMatches_onlineState_success() {
// 准备参数
IotDeviceStateEnum deviceState = IotDeviceStateEnum.ONLINE;
IotDeviceMessage message = createDeviceMessage(deviceState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
deviceState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_InactiveState() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.INACTIVE.getState());
public void testMatches_offlineState_success() {
// 准备参数
IotDeviceStateEnum deviceState = IotDeviceStateEnum.OFFLINE;
IotDeviceMessage message = createDeviceMessage(deviceState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.INACTIVE.getState().toString()
deviceState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_StateMismatch() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
public void testMatches_inactiveState_success() {
// 准备参数
IotDeviceStateEnum deviceState = IotDeviceStateEnum.INACTIVE;
IotDeviceMessage message = createDeviceMessage(deviceState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
deviceState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testMatches_stateMismatch_fail() {
// 准备参数
IotDeviceStateEnum actualState = IotDeviceStateEnum.ONLINE;
IotDeviceStateEnum expectedState = IotDeviceStateEnum.OFFLINE;
IotDeviceMessage message = createDeviceMessage(actualState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
expectedState.getState().toString()
);
// 调用
boolean result = matcher.matches(message, condition);
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_NotEqualsOperator() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
public void testMatches_notEqualsOperator_success() {
// 准备参数
IotDeviceStateEnum actualState = IotDeviceStateEnum.ONLINE;
IotDeviceStateEnum compareState = IotDeviceStateEnum.OFFLINE;
IotDeviceMessage message = createDeviceMessage(actualState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
compareState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_GreaterThanOperator() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.OFFLINE.getState()); // 2
public void testMatches_greaterThanOperator_success() {
// 准备参数
IotDeviceStateEnum actualState = IotDeviceStateEnum.OFFLINE; // 状态值为 2
IotDeviceStateEnum compareState = IotDeviceStateEnum.ONLINE; // 状态值为 1
IotDeviceMessage message = createDeviceMessage(actualState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString() // 1
compareState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_LessThanOperator() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.INACTIVE.getState()); // 0
public void testMatches_lessThanOperator_success() {
// 准备参数
IotDeviceStateEnum actualState = IotDeviceStateEnum.INACTIVE; // 状态值为 0
IotDeviceStateEnum compareState = IotDeviceStateEnum.ONLINE; // 状态值为 1
IotDeviceMessage message = createDeviceMessage(actualState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString() // 1
compareState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_NullCondition() {
// given
public void testMatches_nullCondition_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullConditionType() {
// given
public void testMatches_nullConditionType_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(null);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingOperator() {
// given
public void testMatches_missingOperator_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
condition.setOperator(null);
condition.setParam(IotDeviceStateEnum.ONLINE.getState().toString());
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingParam() {
// given
public void testMatches_missingParam_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
condition.setOperator(IotSceneRuleConditionOperatorEnum.EQUALS.getOperator());
condition.setParam(null);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessage() {
// given
public void testMatches_nullMessage_fail() {
// 准备参数
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(null, condition);
// 调用
boolean result = matcher.matches(null, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullDeviceState() {
// given
public void testMatches_nullDeviceState_fail() {
// 准备参数
IotDeviceMessage message = new IotDeviceMessage();
message.setParams(null);
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_GreaterThanOrEqualsOperator() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState()); // 1
public void testMatches_greaterThanOrEqualsOperator_success() {
// 准备参数
IotDeviceStateEnum deviceState = IotDeviceStateEnum.ONLINE; // 状态值为 1
IotDeviceMessage message = createDeviceMessage(deviceState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString() // 1
deviceState.getState().toString() // 比较值也为 1
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_LessThanOrEqualsOperator() {
// given
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState()); // 1
public void testMatches_lessThanOrEqualsOperator_success() {
// 准备参数
IotDeviceStateEnum actualState = IotDeviceStateEnum.ONLINE; // 状态值为 1
IotDeviceStateEnum compareState = IotDeviceStateEnum.OFFLINE; // 状态值为 2
IotDeviceMessage message = createDeviceMessage(actualState.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString() // 2
compareState.getState().toString()
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_InvalidOperator() {
// given
public void testMatches_invalidOperator_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = new IotSceneRuleDO.TriggerCondition();
condition.setType(IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType());
condition.setOperator("invalid_operator");
condition.setOperator(randomString()); // 随机无效操作符
condition.setParam(IotDeviceStateEnum.ONLINE.getState().toString());
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_InvalidParamFormat() {
// given
public void testMatches_invalidParamFormat_fail() {
// 准备参数
IotDeviceMessage message = createDeviceMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.TriggerCondition condition = createValidCondition(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"invalid_state_value"
randomString() // 随机无效状态值
);
// when
boolean result = matcher.isMatched(message, condition);
// 调用
boolean result = matcher.matches(message, condition);
// then
// 断言
assertFalse(result);
}
@ -317,6 +337,7 @@ public class DeviceStateConditionMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createDeviceMessage(Integer deviceState) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setParams(deviceState);
return message;
}
@ -331,4 +352,5 @@ public class DeviceStateConditionMatcherTest extends BaseMockitoUnitTest {
condition.setParam(param);
return condition;
}
}

View File

@ -6,154 +6,178 @@ 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.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import java.util.HashMap;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.randomInt;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceEventPostTriggerMatcher} 的单元测试
* {@link DeviceEventPostTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceEventPostTriggerMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DeviceEventPostTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceEventPostTriggerMatcher();
@Test
public void testGetSupportedTriggerType_success() {
// 准备参数
// 无需准备参数
// 调用
IotSceneRuleTriggerTypeEnum result = matcher.getSupportedTriggerType();
// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST, result);
}
@Test
public void testGetSupportedTriggerType() {
// when & then
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST, matcher.getSupportedTriggerType());
public void testGetPriority_success() {
// 准备参数
// 无需准备参数
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(30, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(30, matcher.getPriority());
}
public void testIsEnabled_success() {
// 准备参数
// 无需准备参数
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
// 调用
boolean result = matcher.isEnabled();
@Test
public void testIsMatched_Success_AlarmEvent() {
// given
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("message", "Temperature too high")
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_ErrorEvent() {
// given
public void testMatches_alarmEventSuccess() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "error")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("code", 500)
.put("description", "System error")
.put("level", randomString())
.put("message", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("error");
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_InfoEvent() {
// given
public void testMatches_errorEventSuccess() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "info")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("status", "normal")
.put("code", randomInt())
.put("description", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// 调用
boolean result = matcher.matches(message, trigger);
// 断言
assertTrue(result);
}
@Test
public void testMatches_infoEventSuccess() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("status", randomString())
.put("timestamp", System.currentTimeMillis())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("info");
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_EventIdentifierMismatch() {
// given
public void testMatches_eventIdentifierMismatch() {
// 准备参数
String messageIdentifier = randomString();
String triggerIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("identifier", messageIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("error"); // 不匹配的事件标识符
IotSceneRuleDO.Trigger trigger = createValidTrigger(triggerIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_WrongMessageMethod() {
// given
public void testMatches_wrongMessageMethod() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); // 错误的方法
message.setParams(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingIdentifier() {
// given
public void testMatches_nullTriggerIdentifier() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
@ -161,157 +185,166 @@ public class DeviceEventPostTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_EVENT_POST.getType());
trigger.setIdentifier(null); // 缺少标识符
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessageParams() {
// given
public void testMatches_nullMessageParams() {
// 准备参数
String eventIdentifier = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
message.setParams(null);
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_InvalidMessageParams() {
// given
public void testMatches_invalidMessageParams() {
// 准备参数
String eventIdentifier = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
message.setParams("invalid-params"); // 不是 Map 类型
message.setParams(randomString()); // 不是 Map 类型
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingEventIdentifierInParams() {
// given
public void testMatches_missingEventIdentifierInParams() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build()) // 缺少 identifier 字段
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm");
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTrigger() {
// given
public void testMatches_nullTrigger() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTriggerType() {
// given
public void testMatches_nullTriggerType() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "alarm")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(null);
trigger.setIdentifier("alarm");
trigger.setIdentifier(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_ComplexEventValue() {
// given
public void testMatches_complexEventValueSuccess() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "maintenance")
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("type", "scheduled")
.put("duration", 120)
.put("components", new String[]{"motor", "sensor"})
.put("priority", "medium")
.put("type", randomString())
.put("duration", randomInt())
.put("components", new String[]{randomString(), randomString()})
.put("priority", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("maintenance");
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_EmptyEventValue() {
// given
public void testMatches_emptyEventValueSuccess() {
// 准备参数
String eventIdentifier = randomString();
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "heartbeat")
.put("value", MapUtil.of()) // 空的事件值
.put("identifier", eventIdentifier)
.put("value", MapUtil.ofEntries()) // 空的事件值
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("heartbeat");
IotSceneRuleDO.Trigger trigger = createValidTrigger(eventIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_CaseInsensitiveIdentifier() {
// given
public void testMatches_caseSensitiveIdentifierMismatch() {
// 准备参数
String eventIdentifier = randomString().toUpperCase(); // 大写
String triggerIdentifier = eventIdentifier.toLowerCase(); // 小写
Map<String, Object> eventParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "ALARM") // 大写
.put("identifier", eventIdentifier)
.put("value", MapUtil.builder(new HashMap<String, Object>())
.put("level", "high")
.put("level", randomString())
.build())
.build();
IotDeviceMessage message = createEventPostMessage(eventParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("alarm"); // 小写
IotSceneRuleDO.Trigger trigger = createValidTrigger(triggerIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
// 根据实际实现这里可能需要调整期望结果
// 如果实现是大小写敏感的则应该为 false
assertFalse(result);
@ -324,6 +357,7 @@ public class DeviceEventPostTriggerMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createEventPostMessage(Map<String, Object> eventParams) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.EVENT_POST.getMethod());
message.setParams(eventParams);
return message;
@ -338,4 +372,5 @@ public class DeviceEventPostTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setIdentifier(identifier);
return trigger;
}
}

View File

@ -7,268 +7,308 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import java.util.HashMap;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.randomDouble;
import static cn.hutool.core.util.RandomUtil.randomInt;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DevicePropertyPostTriggerMatcher} 的单元测试类
* {@link DevicePropertyPostTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DevicePropertyPostTriggerMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DevicePropertyPostTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DevicePropertyPostTriggerMatcher();
@Test
public void testGetSupportedTriggerType_success() {
// 准备参数
// 无需准备参数
// 调用
IotSceneRuleTriggerTypeEnum result = matcher.getSupportedTriggerType();
// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST, result);
}
@Test
public void testGetSupportedTriggerType() {
// when & then
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST, matcher.getSupportedTriggerType());
public void testGetPriority_success() {
// 准备参数
// 无需准备参数
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(20, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(20, matcher.getPriority());
}
public void testIsEnabled_success() {
// 准备参数
// 无需准备参数
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
// 调用
boolean result = matcher.isEnabled();
@Test
public void testIsMatched_Success_TemperatureProperty() {
// given
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_HumidityProperty() {
// given
public void testMatches_numericPropertyGreaterThanSuccess() {
// 准备参数
String propertyName = randomString();
Double propertyValue = 25.5;
Integer compareValue = 20;
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("humidity", 60)
.put(propertyName, propertyValue)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"humidity",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
String.valueOf(compareValue)
);
// 调用
boolean result = matcher.matches(message, trigger);
// 断言
assertTrue(result);
}
@Test
public void testMatches_integerPropertyEqualsSuccess() {
// 准备参数
String propertyName = randomString();
Integer propertyValue = randomInt();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put(propertyName, propertyValue)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
propertyName,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"60"
String.valueOf(propertyValue)
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_PropertyMismatch() {
// given
public void testMatches_propertyValueNotMeetCondition() {
// 准备参数
String propertyName = randomString();
Double propertyValue = 15.0;
Integer compareValue = 20;
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 15.0)
.put(propertyName, propertyValue)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_PropertyNotFound() {
// given
public void testMatches_propertyNotFound() {
// 准备参数
String existingProperty = randomString();
String missingProperty = randomString();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.put(existingProperty, randomDouble())
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"humidity", // 不存在的属性
missingProperty, // 不存在的属性
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"50"
String.valueOf(randomInt())
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_WrongMessageMethod() {
// given
public void testMatches_wrongMessageMethod() {
// 准备参数
String propertyName = randomString();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.put(propertyName, randomDouble())
.build();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
message.setParams(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
String.valueOf(randomInt())
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingIdentifier() {
// given
public void testMatches_nullTriggerIdentifier() {
// 准备参数
String propertyName = randomString();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.put(propertyName, randomDouble())
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
trigger.setIdentifier(null); // 缺少标识符
trigger.setOperator(IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator());
trigger.setValue("20");
trigger.setValue(String.valueOf(randomInt()));
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessageParams() {
// given
public void testMatches_nullMessageParams() {
// 准备参数
String propertyName = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
message.setParams(null);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
String.valueOf(randomInt())
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_InvalidMessageParams() {
// given
public void testMatches_invalidMessageParams() {
// 准备参数
String propertyName = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
message.setParams("invalid-params"); // 不是 Map 类型
message.setParams(randomString()); // 不是 Map 类型
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
"20"
String.valueOf(randomInt())
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_LessThanOperator() {
// given
public void testMatches_lessThanOperatorSuccess() {
// 准备参数
String propertyName = randomString();
Double propertyValue = 15.0;
Integer compareValue = 20;
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 15.0)
.put(propertyName, propertyValue)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"temperature",
propertyName,
IotSceneRuleConditionOperatorEnum.LESS_THAN.getOperator(),
"20"
String.valueOf(compareValue)
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_NotEqualsOperator() {
// given
public void testMatches_notEqualsOperatorSuccess() {
// 准备参数
String propertyName = randomString();
String propertyValue = randomString();
String compareValue = randomString();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("status", "active")
.put(propertyName, propertyValue)
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"status",
propertyName,
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
"inactive"
compareValue
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_MultipleProperties() {
// given
public void testMatches_multiplePropertiesTargetPropertySuccess() {
// 准备参数
String targetProperty = randomString();
Integer targetValue = randomInt();
Map<String, Object> properties = MapUtil.builder(new HashMap<String, Object>())
.put("temperature", 25.5)
.put("humidity", 60)
.put("status", "active")
.put(randomString(), randomDouble())
.put(targetProperty, targetValue)
.put(randomString(), randomString())
.build();
IotDeviceMessage message = createPropertyPostMessage(properties);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
"humidity",
targetProperty,
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
"60"
String.valueOf(targetValue)
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@ -279,6 +319,7 @@ public class DevicePropertyPostTriggerMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createPropertyPostMessage(Map<String, Object> properties) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
message.setParams(properties);
return message;
@ -295,4 +336,5 @@ public class DevicePropertyPostTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setValue(value);
return trigger;
}
}

View File

@ -6,155 +6,178 @@ 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.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import java.util.HashMap;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.*;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceServiceInvokeTriggerMatcher} 的单元测试
* {@link DeviceServiceInvokeTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceServiceInvokeTriggerMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DeviceServiceInvokeTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceServiceInvokeTriggerMatcher();
@Test
public void testGetSupportedTriggerType_success() {
// 准备参数
// 无需准备参数
// 调用
IotSceneRuleTriggerTypeEnum result = matcher.getSupportedTriggerType();
// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE, result);
}
@Test
public void testGetSupportedTriggerType() {
// when & then
// TODO @puhui999单测按照现有项目的注释风格哈类似 // 调用// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE, matcher.getSupportedTriggerType());
public void testGetPriority_success() {
// 准备参数
// 无需准备参数
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(40, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(40, matcher.getPriority());
}
public void testIsEnabled_success() {
// 准备参数
// 无需准备参数
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
// 调用
boolean result = matcher.isEnabled();
@Test
public void testIsMatched_Success_RestartService() {
// given
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_ConfigService() {
// given
public void testMatches_serviceInvokeSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "config")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("interval", 30)
.put("enabled", true)
.put("threshold", 75.5)
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("config");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_UpdateService() {
// given
public void testMatches_configServiceSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "update")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("version", "1.2.3")
.put("url", "http://example.com/firmware.bin")
.put("interval", randomInt())
.put("enabled", randomBoolean())
.put("threshold", randomDouble())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("update");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_ServiceIdentifierMismatch() {
// given
public void testMatches_updateServiceSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("version", randomString())
.put("url", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("config"); // 不匹配的服务标识符
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testMatches_serviceIdentifierMismatch() {
// 准备参数
String messageIdentifier = randomString();
String triggerIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", messageIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger(triggerIdentifier); // 不匹配的服务标识符
// 调用
boolean result = matcher.matches(message, trigger);
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_WrongMessageMethod() {
// given
public void testMatches_wrongMessageMethod() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); // 错误的方法
message.setParams(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingIdentifier() {
// given
public void testMatches_nullTriggerIdentifier() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
@ -162,178 +185,188 @@ public class DeviceServiceInvokeTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_SERVICE_INVOKE.getType());
trigger.setIdentifier(null); // 缺少标识符
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessageParams() {
// given
public void testMatches_nullMessageParams() {
// 准备参数
String serviceIdentifier = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
message.setParams(null);
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_InvalidMessageParams() {
// given
public void testMatches_invalidMessageParams() {
// 准备参数
String serviceIdentifier = randomString();
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
message.setParams("invalid-params"); // 不是 Map 类型
message.setParams(randomString()); // 不是 Map 类型
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
// 调用
boolean result = matcher.matches(message, trigger);
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingServiceIdentifierInParams() {
// given
public void testMatches_missingServiceIdentifierInParams() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build()) // 缺少 identifier 字段
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTrigger() {
// given
public void testMatches_nullTrigger() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTriggerType() {
// given
public void testMatches_nullTriggerType() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "restart")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(null);
trigger.setIdentifier("restart");
trigger.setIdentifier(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_EmptyInputData() {
// given
public void testMatches_emptyInputDataSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "ping")
.put("inputData", MapUtil.of()) // 空的输入数据
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.ofEntries()) // 空的输入数据
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("ping");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_NoInputData() {
// given
public void testMatches_noInputDataSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "status")
.put("identifier", serviceIdentifier)
// 没有 inputData 字段
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("status");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_ComplexInputData() {
// given
public void testMatches_complexInputDataSuccess() {
// 准备参数
String serviceIdentifier = randomString();
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "calibrate")
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("sensors", new String[]{"temperature", "humidity", "pressure"})
.put("precision", 0.01)
.put("duration", 300)
.put("autoSave", true)
.put("sensors", new String[]{randomString(), randomString(), randomString()})
.put("precision", randomDouble())
.put("duration", randomInt())
.put("autoSave", randomBoolean())
.put("config", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "auto")
.put("level", "high")
.put("mode", randomString())
.put("level", randomString())
.build())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("calibrate");
IotSceneRuleDO.Trigger trigger = createValidTrigger(serviceIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_CaseInsensitiveIdentifier() {
// given
public void testMatches_caseSensitiveIdentifierMismatch() {
// 准备参数
String serviceIdentifier = randomString().toUpperCase(); // 大写
String triggerIdentifier = serviceIdentifier.toLowerCase(); // 小写
Map<String, Object> serviceParams = MapUtil.builder(new HashMap<String, Object>())
.put("identifier", "RESTART") // 大写
.put("identifier", serviceIdentifier)
.put("inputData", MapUtil.builder(new HashMap<String, Object>())
.put("mode", "soft")
.put("mode", randomString())
.build())
.build();
IotDeviceMessage message = createServiceInvokeMessage(serviceParams);
IotSceneRuleDO.Trigger trigger = createValidTrigger("restart"); // 小写
IotSceneRuleDO.Trigger trigger = createValidTrigger(triggerIdentifier);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
// 根据实际实现这里可能需要调整期望结果
// 如果实现是大小写敏感的则应该为 false
assertFalse(result);
@ -346,6 +379,7 @@ public class DeviceServiceInvokeTriggerMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createServiceInvokeMessage(Map<String, Object> serviceParams) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod());
message.setParams(serviceParams);
return message;
@ -360,4 +394,5 @@ public class DeviceServiceInvokeTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setIdentifier(identifier);
return trigger;
}
}

View File

@ -7,216 +7,231 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceStateUpdateTriggerMatcher} 的单元测试
* {@link DeviceStateUpdateTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceStateUpdateTriggerMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private DeviceStateUpdateTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceStateUpdateTriggerMatcher();
@Test
public void testGetSupportedTriggerType_success() {
// 准备参数
// 无需准备参数
// 调用
IotSceneRuleTriggerTypeEnum result = matcher.getSupportedTriggerType();
// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE, result);
}
@Test
public void testGetSupportedTriggerType() {
// when & then
assertEquals(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE, matcher.getSupportedTriggerType());
public void testGetPriority_success() {
// 准备参数
// 无需准备参数
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(10, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(10, matcher.getPriority());
public void testIsEnabled_success() {
// 准备参数
// 无需准备参数
// 调用
boolean result = matcher.isEnabled();
// 断言
assertTrue(result);
}
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
@Test
public void testIsMatched_Success_OnlineState() {
// given
public void testMatches_onlineStateSuccess() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_OfflineState() {
// given
public void testMatches_offlineStateSuccess() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.OFFLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_StateMismatch() {
// given
public void testMatches_stateMismatch() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTrigger() {
// given
public void testMatches_nullTrigger() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTriggerType() {
// given
public void testMatches_nullTriggerType() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(null);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_WrongMessageMethod() {
// given
public void testMatches_wrongMessageMethod() {
// 准备参数
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod());
message.setParams(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingOperator() {
// given
public void testMatches_nullTriggerOperator() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
trigger.setOperator(null);
trigger.setValue(IotDeviceStateEnum.ONLINE.getState().toString());
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_MissingValue() {
// given
public void testMatches_nullTriggerValue() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_STATE_UPDATE.getType());
trigger.setOperator(IotSceneRuleConditionOperatorEnum.EQUALS.getOperator());
trigger.setValue(null);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullMessageParams() {
// given
public void testMatches_nullMessageParams() {
// 准备参数
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
message.setParams(null);
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.EQUALS.getOperator(),
IotDeviceStateEnum.ONLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_GreaterThanOperator() {
// given
public void testMatches_greaterThanOperatorSuccess() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.GREATER_THAN.getOperator(),
IotDeviceStateEnum.INACTIVE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_NotEqualsOperator() {
// given
public void testMatches_notEqualsOperatorSuccess() {
// 准备参数
IotDeviceMessage message = createStateUpdateMessage(IotDeviceStateEnum.ONLINE.getState());
IotSceneRuleDO.Trigger trigger = createValidTrigger(
IotSceneRuleConditionOperatorEnum.NOT_EQUALS.getOperator(),
IotDeviceStateEnum.OFFLINE.getState().toString()
);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@ -227,6 +242,7 @@ public class DeviceStateUpdateTriggerMatcherTest extends BaseMockitoUnitTest {
*/
private IotDeviceMessage createStateUpdateMessage(Integer state) {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
message.setMethod(IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod());
message.setParams(state);
return message;
@ -242,4 +258,5 @@ public class DeviceStateUpdateTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setValue(value);
return trigger;
}
}

View File

@ -4,230 +4,265 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link TimerTriggerMatcher} 的单元测试
* {@link TimerTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class TimerTriggerMatcherTest extends BaseMockitoUnitTest {
@InjectMocks
private TimerTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new TimerTriggerMatcher();
@Test
public void testGetSupportedTriggerType_success() {
// 准备参数
// 无需准备参数
// 调用
IotSceneRuleTriggerTypeEnum result = matcher.getSupportedTriggerType();
// 断言
assertEquals(IotSceneRuleTriggerTypeEnum.TIMER, result);
}
@Test
public void testGetSupportedTriggerType() {
// when & then
assertEquals(IotSceneRuleTriggerTypeEnum.TIMER, matcher.getSupportedTriggerType());
public void testGetPriority_success() {
// 准备参数
// 无需准备参数
// 调用
int result = matcher.getPriority();
// 断言
assertEquals(50, result);
}
@Test
public void testGetPriority() {
// when & then
assertEquals(50, matcher.getPriority());
}
public void testIsEnabled_success() {
// 准备参数
// 无需准备参数
@Test
public void testIsEnabled() {
// when & then
assertTrue(matcher.isEnabled());
}
// 调用
boolean result = matcher.isEnabled();
@Test
public void testIsMatched_Success_ValidCronExpression() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * * ?"); // 每天中午12点
// when
boolean result = matcher.isMatched(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_EveryMinuteCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 * * * * ?"); // 每分钟
public void testMatches_validCronExpressionSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 0 12 * * ?"; // 每天中午12点
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_WeekdaysCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 9 ? * MON-FRI"); // 工作日上午9点
public void testMatches_everyMinuteCronSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 * * * * ?"; // 每分钟
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_InvalidCronExpression() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("invalid-cron-expression");
public void testMatches_weekdaysCronSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 0 9 ? * MON-FRI"; // 工作日上午9点
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testMatches_invalidCronExpression() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = randomString(); // 随机无效的 cron 表达式
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// 调用
boolean result = matcher.matches(message, trigger);
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_EmptyCronExpression() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("");
public void testMatches_emptyCronExpression() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = ""; // 空的 cron 表达式
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullCronExpression() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_nullCronExpression() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
trigger.setCronExpression(null);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTrigger() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_nullTrigger() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
// when
boolean result = matcher.isMatched(message, null);
// 调用
boolean result = matcher.matches(message, null);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Failure_NullTriggerType() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_nullTriggerType() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.Trigger trigger = new IotSceneRuleDO.Trigger();
trigger.setType(null);
trigger.setCronExpression("0 0 12 * * ?");
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_ComplexCronExpression() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 15 10 ? * 6#3"); // 每月第三个星期五上午10:15
public void testMatches_complexCronExpressionSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 15 10 ? * 6#3"; // 每月第三个星期五上午10:15
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_IncorrectCronFormat() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * *"); // 缺少字段
public void testMatches_incorrectCronFormat() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 0 12 * *"; // 缺少字段的 cron 表达式
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_SpecificDateCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 0 1 1 ? 2025"); // 2025年1月1日午夜
public void testMatches_specificDateCronSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 0 0 1 1 ? 2025"; // 2025年1月1日午夜
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Success_EverySecondCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("* * * * * ?"); // 每秒
public void testMatches_everySecondCronSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "* * * * * ?"; // 每秒执行
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
@Test
public void testIsMatched_Failure_InvalidCharactersCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 12 * * @ #"); // 包含无效字符
public void testMatches_invalidCharactersCron() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
String cronExpression = "0 0 12 * * @ #"; // 包含无效字符的 cron 表达式
IotSceneRuleDO.Trigger trigger = createValidTrigger(cronExpression);
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertFalse(result);
}
@Test
public void testIsMatched_Success_RangeCron() {
// given
IotDeviceMessage message = new IotDeviceMessage();
public void testMatches_rangeCronSuccess() {
// 准备参数
IotDeviceMessage message = createDeviceMessage();
IotSceneRuleDO.Trigger trigger = createValidTrigger("0 0 9-17 * * MON-FRI"); // 工作日9-17点
// when
boolean result = matcher.isMatched(message, trigger);
// 调用
boolean result = matcher.matches(message, trigger);
// then
// 断言
assertTrue(result);
}
// ========== 辅助方法 ==========
/**
* 创建设备消息
*/
private IotDeviceMessage createDeviceMessage() {
IotDeviceMessage message = new IotDeviceMessage();
message.setDeviceId(randomLongId());
return message;
}
/**
* 创建有效的定时触发器
*/
@ -237,4 +272,5 @@ public class TimerTriggerMatcherTest extends BaseMockitoUnitTest {
trigger.setCronExpression(cronExpression);
return trigger;
}
}