package com.inspect.nvr.hik.service; import com.inspect.nvr.domain.Infrared.NvrInfo; import com.inspect.nvr.hik.domain.HikNvrCameraTarget; import com.inspect.nvr.hik.exception.HikNvrPlaybackException; import com.inspect.nvr.ivs.mapper.IvsCameraMapper; import com.inspect.nvr.ivs.mapper.IvsNvrMapper; import com.inspect.nvr.ivs.pojo.IvsCamera; import com.inspect.nvr.ivs.pojo.IvsNvr; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.http.HttpStatus; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; /** * 验证页面完整 cameraCode 只会解析到数据库中真实存在的摄像机、NVR 和通道。 */ @RunWith(MockitoJUnitRunner.class) public class HikNvrCameraTargetServiceTest { /** 测试使用的完整 IVS 摄像机编码,最后三位表示通道 2。 */ private static final String CAMERA_CODE = "22078710632508667002#domain-a"; /** 从测试 cameraCode 去掉末三位通道后得到的所属 NVR 编码。 */ private static final String NVR_CODE = "22078710632508667#domain-a"; /** 模拟 ivs_camera 精确编码查询。 */ @Mock private IvsCameraMapper ivsCameraMapper; /** 模拟 basedata_eqpbook_nvr 设备查询。 */ @Mock private IvsNvrMapper ivsNvrMapper; /** 模拟服务端数据库 NVR 凭据解析。 */ @Mock private HikNvrCredentialService credentialService; /** 待测试的 cameraCode 解析服务。 */ private HikNvrCameraTargetService service; /** 创建服务并注入数据库查询替身。 */ @Before public void setUp() { service = new HikNvrCameraTargetService(); // 手工注入三个替身,确保测试不会访问真实数据库或设备。 ReflectionTestUtils.setField(service, "ivsCameraMapper", ivsCameraMapper); ReflectionTestUtils.setField(service, "ivsNvrMapper", ivsNvrMapper); ReflectionTestUtils.setField( service, "credentialService", credentialService); } /** 完整 cameraCode 应精确解析所属启用 NVR、通道号和服务端凭据。 */ @Test public void resolvesCameraCodeToDatabaseNvrAndChannel() { // ivs_camera 必须以完整编码精确命中真实摄像机。 IvsCamera camera = new IvsCamera(); camera.setCode(CAMERA_CODE); when(ivsCameraMapper.selectByCode(CAMERA_CODE)).thenReturn(camera); // NVR 编码与 cameraCode 去掉末三位通道后的结果完全一致。 IvsNvr nvr = new IvsNvr(); nvr.setNvrCode(NVR_CODE); nvr.setNvrIp("192.168.1.249"); nvr.setEnabled(1); when(ivsNvrMapper.selectAll()).thenReturn(Collections.singletonList(nvr)); // 完整连接参数仍由既有凭据服务从数据库读取,浏览器无法传入密码。 NvrInfo nvrInfo = new NvrInfo(); nvrInfo.setNvrIp("192.168.1.249"); when(credentialService.resolveByIp("192.168.1.249")) .thenReturn(nvrInfo); HikNvrCameraTarget target = service.resolve(" " + CAMERA_CODE + " "); assertEquals(CAMERA_CODE, target.getCameraCode()); assertEquals(Integer.valueOf(2), target.getChannel()); assertSame(nvrInfo, target.getNvrInfo()); verify(ivsCameraMapper).selectByCode(CAMERA_CODE); verify(credentialService).resolveByIp("192.168.1.249"); } /** 缺少 cameraCode 时必须在访问数据库前立即返回参数错误。 */ @Test public void rejectsMissingCameraCodeBeforeDatabaseLookup() { try { // 空白输入既不能唯一定位摄像机,也不允许回退到第一台设备。 service.resolve(" "); fail("Expected HikNvrPlaybackException"); } catch (HikNvrPlaybackException exception) { assertEquals(HttpStatus.BAD_REQUEST, exception.getStatus()); assertEquals("cameraCode不能为空", exception.getMessage()); } // 参数结构无效时不应触发摄像机、NVR 或凭据数据库查询。 verifyNoInteractions( ivsCameraMapper, ivsNvrMapper, credentialService); } /** 数据库没有精确 cameraCode 时不得仅凭编码末三位推断设备。 */ @Test public void rejectsCameraCodeMissingFromIvsCamera() { // 精确查询无结果,模拟页面提交已经删除或伪造的摄像机编码。 when(ivsCameraMapper.selectByCode(CAMERA_CODE)).thenReturn(null); try { service.resolve(CAMERA_CODE); fail("Expected HikNvrPlaybackException"); } catch (HikNvrPlaybackException exception) { assertEquals(HttpStatus.NOT_FOUND, exception.getStatus()); } // 摄像机不存在时不能继续扫描 NVR 或读取任何设备凭据。 verifyNoInteractions(ivsNvrMapper, credentialService); } }