7 小时以前 b29d86d9ed34fd890eb14cb7a75f6ae4f7148865
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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;
    }
 
}