package com.ruoyi.system.service.impl; import java.math.BigDecimal; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; 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.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.system.domain.TDetectionCabinet; import com.ruoyi.system.mapper.TDetectionCabinetMapper; /** * 检测柜业务层单元测试,验证字段规范化、状态限制及唯一性校验等关键规则。 */ @ExtendWith(MockitoExtension.class) class TDetectionCabinetServiceImplTest { @Mock private TDetectionCabinetMapper detectionCabinetMapper; @InjectMocks private TDetectionCabinetServiceImpl detectionCabinetService; private TDetectionCabinet detectionCabinet; /** * 初始化一条满足新增校验的检测柜 Mock 数据。 */ @BeforeEach void setUp() { detectionCabinet = new TDetectionCabinet(); detectionCabinet.setCabinetCode(" CABINET-001 "); detectionCabinet.setCabinetName(" 一号检测柜 "); detectionCabinet.setIpAddress(" 192.168.1.10 "); detectionCabinet.setMacAddress("aa-bb-cc-dd-ee-ff"); detectionCabinet.setManufacturer(" 厂商 "); detectionCabinet.setModel(" 型号A "); detectionCabinet.setCapacity(new BigDecimal("120.50")); detectionCabinet.setChannelCount(8); detectionCabinet.setRemark(" 备注 "); } /** * 验证新增时会规范化基础字段并初始化运行状态。 */ @Test void insertDetectionCabinetShouldNormalizeFieldsAndInitializeStatus() { when(detectionCabinetMapper.selectByCabinetCode("CABINET-001")).thenReturn(null); when(detectionCabinetMapper.selectByMacAddress("AA:BB:CC:DD:EE:FF")).thenReturn(null); when(detectionCabinetMapper.insertDetectionCabinet(any(TDetectionCabinet.class))).thenReturn(1); int rows = detectionCabinetService.insertDetectionCabinet(detectionCabinet); ArgumentCaptor captor = ArgumentCaptor.forClass(TDetectionCabinet.class); verify(detectionCabinetMapper).insertDetectionCabinet(captor.capture()); TDetectionCabinet savedCabinet = captor.getValue(); assertEquals(1, rows); assertEquals("CABINET-001", savedCabinet.getCabinetCode()); assertEquals("一号检测柜", savedCabinet.getCabinetName()); assertEquals("192.168.1.10", savedCabinet.getIpAddress()); assertEquals("AA:BB:CC:DD:EE:FF", savedCabinet.getMacAddress()); assertEquals(new BigDecimal("120.50"), savedCabinet.getCapacity()); assertEquals("0", savedCabinet.getOnlineStatus()); assertEquals("0", savedCabinet.getTestStatus()); assertEquals("0", savedCabinet.getStatus()); assertEquals("0", savedCabinet.getDelFlag()); assertNull(savedCabinet.getCurrentTest()); } /** * 验证重复设备编码会阻止新增且不会执行写库操作。 */ @Test void insertDetectionCabinetShouldRejectDuplicateCabinetCode() { TDetectionCabinet existing = new TDetectionCabinet(); existing.setCabinetId(2L); when(detectionCabinetMapper.selectByCabinetCode("CABINET-001")).thenReturn(existing); ServiceException exception = assertThrows(ServiceException.class, () -> detectionCabinetService.insertDetectionCabinet(detectionCabinet)); assertEquals("设备编码已存在", exception.getMessage()); verify(detectionCabinetMapper, never()).insertDetectionCabinet(any(TDetectionCabinet.class)); } /** * 验证非法 IP 地址会阻止新增。 */ @Test void insertDetectionCabinetShouldRejectInvalidIpAddress() { detectionCabinet.setIpAddress("invalid-ip"); ServiceException exception = assertThrows(ServiceException.class, () -> detectionCabinetService.insertDetectionCabinet(detectionCabinet)); assertEquals("IP地址格式不正确", exception.getMessage()); verify(detectionCabinetMapper, never()).insertDetectionCabinet(any(TDetectionCabinet.class)); } /** * 验证测试中的检测柜不能被禁用。 */ @Test void updateDetectionCabinetStatusShouldRejectDisablingTestingCabinet() { TDetectionCabinet current = new TDetectionCabinet(); current.setCabinetId(1L); current.setStatus("0"); current.setTestStatus("1"); when(detectionCabinetMapper.selectDetectionCabinetById(1L)).thenReturn(current); TDetectionCabinet statusCommand = new TDetectionCabinet(); statusCommand.setCabinetId(1L); statusCommand.setStatus("1"); ServiceException exception = assertThrows(ServiceException.class, () -> detectionCabinetService.updateDetectionCabinetStatus(statusCommand)); assertEquals("检测柜正在测试,不能禁用", exception.getMessage()); verify(detectionCabinetMapper, never()).updateDetectionCabinetStatus(any(TDetectionCabinet.class)); } /** * 验证检测中的检测柜允许执行启用操作。 */ @Test void updateDetectionCabinetStatusShouldAllowEnablingTestingCabinet() { TDetectionCabinet current = new TDetectionCabinet(); current.setCabinetId(1L); current.setStatus("1"); current.setTestStatus("1"); when(detectionCabinetMapper.selectDetectionCabinetById(1L)).thenReturn(current); when(detectionCabinetMapper.updateDetectionCabinetStatus(any(TDetectionCabinet.class))).thenReturn(1); TDetectionCabinet statusCommand = new TDetectionCabinet(); statusCommand.setCabinetId(1L); statusCommand.setStatus("0"); int rows = detectionCabinetService.updateDetectionCabinetStatus(statusCommand); assertEquals(1, rows); verify(detectionCabinetMapper).updateDetectionCabinetStatus(statusCommand); } /** * 验证重复提交相同状态时按幂等成功处理,不重复写库。 */ @Test void updateDetectionCabinetStatusShouldBeIdempotent() { TDetectionCabinet current = new TDetectionCabinet(); current.setCabinetId(1L); current.setStatus("0"); current.setTestStatus("0"); when(detectionCabinetMapper.selectDetectionCabinetById(1L)).thenReturn(current); TDetectionCabinet statusCommand = new TDetectionCabinet(); statusCommand.setCabinetId(1L); statusCommand.setStatus("0"); int rows = detectionCabinetService.updateDetectionCabinetStatus(statusCommand); assertEquals(1, rows); verify(detectionCabinetMapper, never()).updateDetectionCabinetStatus(any(TDetectionCabinet.class)); } /** * 验证批量删除会先检查所有检测柜,存在测试中记录时不删除任何数据。 */ @Test void deleteDetectionCabinetByIdsShouldRejectTestingCabinetBeforeDeleting() { TDetectionCabinet normal = new TDetectionCabinet(); normal.setCabinetId(1L); normal.setTestStatus("0"); TDetectionCabinet testing = new TDetectionCabinet(); testing.setCabinetId(2L); testing.setTestStatus("1"); when(detectionCabinetMapper.selectDetectionCabinetById(1L)).thenReturn(normal); when(detectionCabinetMapper.selectDetectionCabinetById(2L)).thenReturn(testing); ServiceException exception = assertThrows(ServiceException.class, () -> detectionCabinetService.deleteDetectionCabinetByIds(new Long[] { 1L, 2L }, "admin")); assertEquals("检测柜正在测试,不能删除", exception.getMessage()); verify(detectionCabinetMapper, never()).deleteDetectionCabinetById(any(), any()); } /** * 验证编辑时唯一性查询命中当前记录仍视为唯一。 */ @Test void checkUniqueShouldAllowCurrentCabinet() { TDetectionCabinet current = new TDetectionCabinet(); current.setCabinetId(1L); current.setCabinetCode("CABINET-001"); current.setMacAddress("AA:BB:CC:DD:EE:FF"); when(detectionCabinetMapper.selectByCabinetCode("CABINET-001")).thenReturn(current); when(detectionCabinetMapper.selectByMacAddress("AA:BB:CC:DD:EE:FF")).thenReturn(current); assertTrue(detectionCabinetService.checkCabinetCodeUnique(current)); assertTrue(detectionCabinetService.checkMacAddressUnique(current)); } }