package com.ruoyi.system.service.impl;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.nio.charset.StandardCharsets;
|
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.system.domain.TCollector;
|
import com.ruoyi.system.mapper.TCollectorMapper;
|
import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore;
|
import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate;
|
|
/**
|
* 采集器 Service 单元测试。
|
*/
|
@ExtendWith(MockitoExtension.class)
|
class TCollectorServiceImplTest
|
{
|
@Mock
|
private TCollectorMapper collectorMapper;
|
|
private TCollectorServiceImpl collectorService;
|
private InMemoryDeviceDiscoveryCandidateStore candidateStore;
|
|
private TCollector collector;
|
|
@BeforeEach
|
void setUp()
|
{
|
candidateStore = new InMemoryDeviceDiscoveryCandidateStore();
|
collectorService = new TCollectorServiceImpl(collectorMapper, candidateStore);
|
java.time.Instant now = java.time.Instant.now();
|
candidateStore.replaceCollectors("dev-sim", java.util.List.of(new CollectorCandidate(
|
"dev-sim", "COL-001", "192.168.1.10", "AA:BB:CC:DD:EE:FF", "一号采集器",
|
"开发模拟器", "Virtual Collector", 8, true, now, now.plusSeconds(60))));
|
collector = new TCollector();
|
collector.setCollectorId(1L);
|
collector.setCollectorCode("COL-001");
|
collector.setIpAddress("192.168.1.10");
|
collector.setMacAddress("AA:BB:CC:DD:EE:FF");
|
collector.setCollectorName("一号采集器");
|
collector.setChannelCount(8);
|
collector.setOnlineStatus("0");
|
collector.setTestStatus("0");
|
collector.setStatus("0");
|
}
|
|
@Test
|
void insertCollectorSqlShouldNotWriteUpdateAuditFields() throws IOException
|
{
|
try (InputStream input = getClass().getResourceAsStream(
|
"/mapper/system/TCollectorMapper.xml"))
|
{
|
assertNotNull(input);
|
String mapperXml = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
int insertStart = mapperXml.indexOf("<insert id=\"insertCollector\"");
|
int insertEnd = mapperXml.indexOf("</insert>", insertStart);
|
String insertSql = mapperXml.substring(insertStart, insertEnd);
|
|
assertFalse(insertSql.contains("update_by"));
|
assertFalse(insertSql.contains("update_time"));
|
}
|
}
|
|
@Test
|
void registeredCollectorCodeSqlShouldIgnoreDeletedRows() throws IOException
|
{
|
try (InputStream input = getClass().getResourceAsStream(
|
"/mapper/system/TCollectorMapper.xml"))
|
{
|
assertNotNull(input);
|
String mapperXml = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
int selectStart = mapperXml.indexOf("<select id=\"selectRegisteredCollectorCodes\"");
|
assertTrue(selectStart >= 0);
|
int selectEnd = mapperXml.indexOf("</select>", selectStart);
|
String selectSql = mapperXml.substring(selectStart, selectEnd);
|
|
assertTrue(selectSql.contains("where del_flag = '0'"));
|
}
|
}
|
|
@Test
|
void insertCollectorShouldNormalizeFieldsAndInitializeStatus()
|
{
|
collector.setCollectorId(null);
|
collector.setCollectorCode(" COL-001 ");
|
collector.setMacAddress("aa-bb-cc-dd-ee-ff");
|
when(collectorMapper.insertCollector(any(TCollector.class))).thenReturn(1);
|
|
int rows = collectorService.insertCollector(collector);
|
|
ArgumentCaptor<TCollector> captor = ArgumentCaptor.forClass(TCollector.class);
|
verify(collectorMapper).insertCollector(captor.capture());
|
TCollector saved = captor.getValue();
|
assertEquals(1, rows);
|
assertEquals("COL-001", saved.getCollectorCode());
|
assertEquals("AA:BB:CC:DD:EE:FF", saved.getMacAddress());
|
assertEquals("0", saved.getOnlineStatus());
|
assertEquals("0", saved.getTestStatus());
|
assertEquals("0", saved.getStatus());
|
assertEquals("0", saved.getDelFlag());
|
}
|
|
@Test
|
void insertCollectorShouldRetainRequestedDisabledStatus()
|
{
|
collector.setCollectorId(null);
|
collector.setStatus("1");
|
when(collectorMapper.insertCollector(any(TCollector.class))).thenReturn(1);
|
|
assertEquals(1, collectorService.insertCollector(collector));
|
|
ArgumentCaptor<TCollector> captor = ArgumentCaptor.forClass(TCollector.class);
|
verify(collectorMapper).insertCollector(captor.capture());
|
assertEquals("1", captor.getValue().getStatus());
|
}
|
|
@Test
|
void insertCollectorShouldDefaultToEnabledWhenStatusIsMissing()
|
{
|
collector.setCollectorId(null);
|
collector.setStatus(null);
|
when(collectorMapper.insertCollector(any(TCollector.class))).thenReturn(1);
|
|
assertEquals(1, collectorService.insertCollector(collector));
|
|
ArgumentCaptor<TCollector> captor = ArgumentCaptor.forClass(TCollector.class);
|
verify(collectorMapper).insertCollector(captor.capture());
|
assertEquals("0", captor.getValue().getStatus());
|
}
|
|
@Test
|
void insertCollectorShouldValidateAuthoritativeCandidateTopology()
|
{
|
collector.setCollectorId(null);
|
collector.setIpAddress("invalid-host");
|
collector.setMacAddress("invalid-mac");
|
collector.setChannelCount(99);
|
when(collectorMapper.insertCollector(any(TCollector.class))).thenReturn(1);
|
|
assertEquals(1, collectorService.insertCollector(collector));
|
|
ArgumentCaptor<TCollector> captor = ArgumentCaptor.forClass(TCollector.class);
|
verify(collectorMapper).insertCollector(captor.capture());
|
assertEquals("192.168.1.10", captor.getValue().getIpAddress());
|
assertEquals("AA:BB:CC:DD:EE:FF", captor.getValue().getMacAddress());
|
assertEquals(8, captor.getValue().getChannelCount());
|
}
|
|
@Test
|
void insertCollectorShouldRejectDuplicateCode()
|
{
|
collector.setCollectorId(null);
|
TCollector existing = new TCollector();
|
existing.setCollectorId(2L);
|
when(collectorMapper.selectCollectorByCode("COL-001")).thenReturn(existing);
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> collectorService.insertCollector(collector));
|
|
assertEquals("设备编码已存在", exception.getMessage());
|
verify(collectorMapper, never()).insertCollector(any(TCollector.class));
|
}
|
|
@Test
|
void updateCollectorShouldAllowCurrentUniqueValues()
|
{
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(collector);
|
when(collectorMapper.selectCollectorByCode("COL-001")).thenReturn(collector);
|
when(collectorMapper.selectCollectorByMacAddress("AA:BB:CC:DD:EE:FF")).thenReturn(collector);
|
when(collectorMapper.updateCollector(any(TCollector.class))).thenReturn(1);
|
|
assertEquals(1, collectorService.updateCollector(collector));
|
|
verify(collectorMapper).updateCollector(collector);
|
}
|
|
@Test
|
void updateCollectorShouldRejectDisablingTestingCollector()
|
{
|
collector.setStatus("1");
|
collector.setTestStatus("1");
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(collector);
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> collectorService.updateCollector(collector));
|
|
assertEquals("采集器正在测试,不能禁用", exception.getMessage());
|
verify(collectorMapper, never()).updateCollector(any(TCollector.class));
|
}
|
|
@Test
|
void updateCollectorStatusShouldRejectDisablingTestingCollector()
|
{
|
collector.setTestStatus("1");
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(collector);
|
TCollector command = statusCommand("1");
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> collectorService.updateCollectorStatus(command));
|
|
assertEquals("采集器正在测试,不能禁用", exception.getMessage());
|
verify(collectorMapper, never()).updateCollectorStatus(any(TCollector.class));
|
}
|
|
@Test
|
void updateCollectorStatusShouldAllowEnablingTestingCollector()
|
{
|
collector.setTestStatus("1");
|
collector.setStatus("1");
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(collector);
|
when(collectorMapper.updateCollectorStatus(any(TCollector.class))).thenReturn(1);
|
TCollector command = statusCommand("0");
|
|
assertEquals(1, collectorService.updateCollectorStatus(command));
|
|
verify(collectorMapper).updateCollectorStatus(command);
|
}
|
|
@Test
|
void updateCollectorStatusShouldBeIdempotent()
|
{
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(collector);
|
TCollector command = statusCommand("0");
|
|
assertEquals(1, collectorService.updateCollectorStatus(command));
|
|
verify(collectorMapper, never()).updateCollectorStatus(any(TCollector.class));
|
}
|
|
@Test
|
void selectRegisteredCollectorCodesShouldReturnUndeletedCodes()
|
{
|
when(collectorMapper.selectRegisteredCollectorCodes()).thenReturn(java.util.List.of("COL-001"));
|
|
assertEquals(java.util.Set.of("COL-001"), collectorService.selectRegisteredCollectorCodes());
|
}
|
|
@Test
|
void deleteCollectorByIdsShouldRejectTestingCollectorBeforeAnyDelete()
|
{
|
TCollector idle = new TCollector();
|
idle.setCollectorId(1L);
|
idle.setTestStatus("0");
|
TCollector testing = new TCollector();
|
testing.setCollectorId(2L);
|
testing.setTestStatus("1");
|
when(collectorMapper.selectCollectorById(1L)).thenReturn(idle);
|
when(collectorMapper.selectCollectorById(2L)).thenReturn(testing);
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> collectorService.deleteCollectorByIds(new Long[] { 1L, 2L }, "admin"));
|
|
assertEquals("采集器正在测试,不能删除", exception.getMessage());
|
verify(collectorMapper, never()).deleteCollectorById(anyLong(), any(String.class));
|
}
|
|
private TCollector statusCommand(String status)
|
{
|
TCollector command = new TCollector();
|
command.setCollectorId(1L);
|
command.setStatus(status);
|
command.setUpdateBy("admin");
|
return command;
|
}
|
}
|