浇水bug修改
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package org.dromara.mqtt;
|
||||
|
||||
import org.dromara.mqtt.config.properties.MqttProperties;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.invokeMethod;
|
||||
|
||||
@Tag("dev")
|
||||
class DeviceMqttCommandPublisherTest {
|
||||
|
||||
@Test
|
||||
void buildCommandTopicDefaultsToDeviceNo() {
|
||||
MqttProperties properties = new MqttProperties();
|
||||
DeviceMqttCommandPublisher publisher = new DeviceMqttCommandPublisher(
|
||||
null,
|
||||
null,
|
||||
properties
|
||||
);
|
||||
|
||||
String topic = invokeMethod(publisher, "buildCommandTopic", "D01");
|
||||
|
||||
assertThat(topic).isEqualTo("/d01/subscriber/cmd");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.dromara.mqtt;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.dromara.app.domain.AppDevice;
|
||||
import org.dromara.app.domain.mqtt.DeviceCommand;
|
||||
import org.dromara.app.domain.mqtt.DeviceCommandAck;
|
||||
import org.dromara.app.mapper.AppDeviceMapper;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.mqtt.config.properties.MqttProperties;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@Tag("dev")
|
||||
class MqttCommandAckServiceTest {
|
||||
|
||||
private static GenericApplicationContext applicationContext;
|
||||
|
||||
@BeforeAll
|
||||
static void initializeRedisUtils() {
|
||||
if (TableInfoHelper.getTableInfo(AppDevice.class) == null) {
|
||||
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new Configuration(), ""), AppDevice.class);
|
||||
}
|
||||
applicationContext = new GenericApplicationContext();
|
||||
applicationContext.registerBean(RedissonClient.class, () -> mock(RedissonClient.class));
|
||||
applicationContext.refresh();
|
||||
new SpringUtil().setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void closeApplicationContext() {
|
||||
applicationContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveMissingCommandId_usesSinglePendingCommandForDevice() {
|
||||
DeviceCommandAck ack = new DeviceCommandAck();
|
||||
ack.setCommandId("");
|
||||
|
||||
DeviceCommand pending = new DeviceCommand();
|
||||
pending.setCommandId("cmd-1");
|
||||
pending.setDeviceNo("D01");
|
||||
|
||||
boolean resolved = MqttCommandAckService.resolveMissingCommandId(ack, List.of(pending));
|
||||
|
||||
assertThat(resolved).isTrue();
|
||||
assertThat(ack.getCommandId()).isEqualTo("cmd-1");
|
||||
assertThat(ack.getStatus()).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveMissingCommandId_refusesAmbiguousPendingCommands() {
|
||||
DeviceCommandAck ack = new DeviceCommandAck();
|
||||
ack.setCommandId("");
|
||||
|
||||
DeviceCommand first = new DeviceCommand();
|
||||
first.setCommandId("cmd-1");
|
||||
DeviceCommand second = new DeviceCommand();
|
||||
second.setCommandId("cmd-2");
|
||||
|
||||
boolean resolved = MqttCommandAckService.resolveMissingCommandId(ack, List.of(first, second));
|
||||
|
||||
assertThat(resolved).isFalse();
|
||||
assertThat(ack.getCommandId()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void ackMatchesPendingCommandRequiresSameDevice() {
|
||||
DeviceCommand pending = new DeviceCommand();
|
||||
pending.setDeviceNo("D01");
|
||||
|
||||
assertThat(MqttCommandAckService.ackMatchesPendingCommand("D01", pending)).isTrue();
|
||||
assertThat(MqttCommandAckService.ackMatchesPendingCommand("D02", pending)).isFalse();
|
||||
assertThat(MqttCommandAckService.ackMatchesPendingCommand("D01", null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshDeviceOnlineRenewsStatusCacheTtl() throws Exception {
|
||||
MqttProperties properties = new MqttProperties();
|
||||
properties.getCommandAck().setDeviceStatusCacheTtlSeconds(900);
|
||||
AppDeviceMapper appDeviceMapper = mock(AppDeviceMapper.class);
|
||||
RedissonClient redissonClient = mock(RedissonClient.class);
|
||||
RLock lock = mock(RLock.class);
|
||||
when(redissonClient.getLock("lock:mqtt:device:status:D01")).thenReturn(lock);
|
||||
when(lock.tryLock(0, 10, TimeUnit.SECONDS)).thenReturn(true);
|
||||
when(lock.isHeldByCurrentThread()).thenReturn(true);
|
||||
|
||||
MqttCommandAckService service = new MqttCommandAckService(properties, appDeviceMapper);
|
||||
try (MockedStatic<RedisUtils> redis = mockStatic(RedisUtils.class)) {
|
||||
redis.when(RedisUtils::getClient).thenReturn(redissonClient);
|
||||
|
||||
ReflectionTestUtils.invokeMethod(service, "refreshDeviceOnline", "D01");
|
||||
|
||||
redis.verify(() -> RedisUtils.setCacheObject(
|
||||
eq("mqtt:device:status:D01"),
|
||||
any(Map.class),
|
||||
eq(Duration.ofSeconds(900))
|
||||
));
|
||||
verify(appDeviceMapper).update(eq(null), any());
|
||||
verify(lock).unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user