package cn.iocoder.yudao.module.mes.service.trace.integrity;
|
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.module.mes.controller.admin.trace.integrity.vo.MesTraceIntegrityVerifyRespVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.trace.consumer.MesTraceConsumerScanEventDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.trace.integrity.MesTraceIntegrityRecordDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.trace.consumer.MesTraceConsumerScanEventMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.trace.integrity.MesTraceIntegrityRecordMapper;
|
import cn.iocoder.yudao.module.mes.enums.trace.MesTraceIntegrityBizTypeEnum;
|
import jakarta.annotation.Resource;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.context.annotation.Import;
|
|
import java.time.LocalDateTime;
|
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MES_TRACE_INTEGRITY_BIZ_TYPE_INVALID;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MES_TRACE_INTEGRITY_RECORD_NOT_EXISTS;
|
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;
|
|
/**
|
* {@link MesTraceIntegrityServiceImpl} 的单元测试
|
*
|
* @author 超级管理员
|
*/
|
@Import(MesTraceIntegrityServiceImpl.class)
|
public class MesTraceIntegrityServiceImplTest extends BaseDbUnitTest {
|
|
@Resource
|
private MesTraceIntegrityService integrityService;
|
@Resource
|
private MesTraceIntegrityRecordMapper integrityRecordMapper;
|
@Resource
|
private MesTraceConsumerScanEventMapper scanEventMapper;
|
|
@Test
|
public void testRecordScanIntegrity_生成摘要并入库() {
|
MesTraceConsumerScanEventDO event = insertEvent("江苏省", "南京市");
|
integrityService.recordScanIntegrity(event);
|
|
MesTraceIntegrityRecordDO record = integrityRecordMapper.selectByBiz(
|
MesTraceIntegrityBizTypeEnum.SCAN.getType(), event.getId());
|
assertNotNull(record);
|
assertEquals(64, record.getContentHash().length());
|
assertEquals(event.getNormalizedCode(), record.getBizCode());
|
}
|
|
@Test
|
public void testVerify_数据完整通过() {
|
MesTraceConsumerScanEventDO event = insertEvent("江苏省", "南京市");
|
integrityService.recordScanIntegrity(event);
|
|
MesTraceIntegrityVerifyRespVO vo = integrityService.verify(
|
MesTraceIntegrityBizTypeEnum.SCAN.getType(), event.getId());
|
|
assertTrue(vo.getMatched());
|
assertEquals(vo.getStoredHash(), vo.getCurrentHash());
|
assertEquals(event.getNormalizedCode(), vo.getBizCode());
|
}
|
|
@Test
|
public void testVerify_篡改检测失败() {
|
MesTraceConsumerScanEventDO event = insertEvent("江苏省", "南京市");
|
integrityService.recordScanIntegrity(event);
|
// 模拟事后篡改扫码地区
|
scanEventMapper.updateById(new MesTraceConsumerScanEventDO().setId(event.getId()).setProvince("浙江省"));
|
|
MesTraceIntegrityVerifyRespVO vo = integrityService.verify(
|
MesTraceIntegrityBizTypeEnum.SCAN.getType(), event.getId());
|
|
assertFalse(vo.getMatched());
|
assertEquals("数据不一致,可能存在篡改", vo.getMessage());
|
}
|
|
@Test
|
public void testVerify_覆盖更新不产生重复记录() {
|
MesTraceConsumerScanEventDO event = insertEvent("江苏省", "南京市");
|
integrityService.recordScanIntegrity(event);
|
integrityService.recordScanIntegrity(event);
|
|
assertEquals(1L, integrityRecordMapper.selectCount());
|
MesTraceIntegrityRecordDO record = integrityRecordMapper.selectByBiz(
|
MesTraceIntegrityBizTypeEnum.SCAN.getType(), event.getId());
|
assertEquals(64, record.getContentHash().length());
|
}
|
|
@Test
|
public void testVerify_无摘要记录异常() {
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> integrityService.verify(MesTraceIntegrityBizTypeEnum.SCAN.getType(), 99999L));
|
assertEquals(MES_TRACE_INTEGRITY_RECORD_NOT_EXISTS.getCode(), ex.getCode());
|
}
|
|
@Test
|
public void testVerify_非法业务类型() {
|
ServiceException ex = assertThrows(ServiceException.class,
|
() -> integrityService.verify("XXX", 1L));
|
assertEquals(MES_TRACE_INTEGRITY_BIZ_TYPE_INVALID.getCode(), ex.getCode());
|
}
|
|
@Test
|
public void testRecordScanIntegrity_null事件容错() {
|
integrityService.recordScanIntegrity(null);
|
integrityService.recordScanIntegrity(MesTraceConsumerScanEventDO.builder().id(null).build());
|
assertEquals(0L, integrityRecordMapper.selectCount());
|
}
|
|
// ==================== 辅助方法 ====================
|
|
private MesTraceConsumerScanEventDO insertEvent(String province, String city) {
|
MesTraceConsumerScanEventDO event = MesTraceConsumerScanEventDO.builder()
|
.traceCode("BAG-00000001")
|
.normalizedCode("BAG-00000001")
|
.sourceType("BAG")
|
.province(province)
|
.city(city)
|
.batchId(10L)
|
.success(true)
|
.eventTime(LocalDateTime.of(2026, 9, 1, 10, 0))
|
.build();
|
scanEventMapper.insert(event);
|
return event;
|
}
|
|
}
|