From 43aab58c9ecb1203770ba382efbdbae299ca87ec Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 26 十月 2026 15:12:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business
---
yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 171 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java b/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java
new file mode 100644
index 0000000..fc0d17b
--- /dev/null
+++ b/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java
@@ -0,0 +1,171 @@
+package cn.iocoder.yudao.module.mdm.service.agent;
+
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportCommitReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportPreflightReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportPreflightRespVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportReceiptRespVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.agent.MdmAgentImportCommandDO;
+import cn.iocoder.yudao.module.mdm.dal.mysql.agent.MdmAgentImportCommandMapper;
+import cn.iocoder.yudao.module.mdm.dal.mysql.agent.MdmAgentImportCommandRowMapper;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemImportContext;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemRowResolution;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemService;
+import cn.iocoder.yudao.module.system.framework.agent.AgentBridgeException;
+import cn.iocoder.yudao.module.system.framework.agent.AgentPrincipal;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class MdmAgentImportCommandServiceTest {
+
+ private static final String PREFLIGHT_HASH = "b".repeat(64);
+ private static final String SOURCE_SHA = "a".repeat(64);
+
+ @Mock private MdmAgentImportPreflightService preflightService;
+ @Mock private MdmItemService itemService;
+ @Mock private MdmAgentImportPolicy policy;
+ @Mock private MdmAgentImportCommandMapper commandMapper;
+ @Mock private MdmAgentImportCommandRowMapper commandRowMapper;
+ @Mock private PlatformTransactionManager transactionManager;
+ @InjectMocks private MdmAgentImportCommandService service;
+
+ private final AgentPrincipal principal = new AgentPrincipal(7L, "live");
+
+ @BeforeEach
+ void setUp() {
+ when(policy.isWriteEnabled()).thenReturn(true);
+ when(transactionManager.getTransaction(any(TransactionDefinition.class)))
+ .thenReturn(mock(TransactionStatus.class));
+ when(itemService.buildImportContext(any())).thenReturn(new MdmItemImportContext(
+ Map.of("RAW", 11L), Map.of("RAW", "鍘熸枡"),
+ Map.of("PCS", 22L), Map.of("PCS", "涓�")));
+ when(itemService.resolveImportRow(any(MdmItemImportExcelVO.class), any()))
+ .thenAnswer(invocation -> MdmItemRowResolution.success(new MdmItemSaveReqVO()));
+ when(itemService.getItemListByCode(any())).thenReturn(List.of());
+ when(itemService.createItem(any())).thenReturn(77L);
+ when(commandRowMapper.selectListByCommandId(any())).thenReturn(List.of());
+ }
+
+ @Test
+ void writeDisabledRejects() {
+ when(policy.isWriteEnabled()).thenReturn(false);
+ AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+ () -> service.commit(request("鐗╂枡A"), principal));
+ assertEquals("WRITE_DISABLED", ex.getErrorCode());
+ verify(itemService, never()).createItem(any());
+ }
+
+ @Test
+ void repeatedCommitCreatesItemOnceAndReplaysReceipt() {
+ stubPreflight(PREFLIGHT_HASH);
+ AtomicReference<MdmAgentImportCommandDO> inserted = captureInsertedCommand();
+
+ MdmAgentImportReceiptRespVO first = service.commit(request("鐗╂枡A"), principal);
+ when(commandMapper.selectByCommandId(7L, "cmd-1")).thenReturn(inserted.get());
+ MdmAgentImportReceiptRespVO second = service.commit(request("鐗╂枡A"), principal);
+
+ assertEquals("SUCCEEDED", first.getStatus());
+ assertEquals("SUCCEEDED", second.getStatus());
+ assertEquals(first.getPreflightHash(), second.getPreflightHash());
+ verify(itemService, times(1)).createItem(any());
+ }
+
+ @Test
+ void sameCommandWithDifferentContentConflicts() {
+ when(preflightService.preflight(any(), any())).thenReturn(preflight(PREFLIGHT_HASH));
+ AtomicReference<MdmAgentImportCommandDO> inserted = captureInsertedCommand();
+ service.commit(request("鐗╂枡A"), principal);
+ when(commandMapper.selectByCommandId(7L, "cmd-1")).thenReturn(inserted.get());
+ when(commandMapper.selectByIdempotencyKey(7L, "idem-1")).thenReturn(null);
+
+ AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+ () -> service.commit(request("鐗╂枡B"), principal));
+ assertEquals("COMMAND_ID_CONFLICT", ex.getErrorCode());
+ }
+
+ @Test
+ void stalePreflightIsRejected() {
+ stubPreflight("c".repeat(64));
+
+ AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+ () -> service.commit(request("鐗╂枡A"), principal));
+ assertEquals("PLAN_STALE", ex.getErrorCode());
+ verify(commandMapper, never()).insert(any(MdmAgentImportCommandDO.class));
+ }
+
+ @Test
+ void missingCommandReturnsNotFound() {
+ when(commandMapper.selectByCommandId(7L, "cmd-x")).thenReturn(null);
+
+ AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+ () -> service.getCommand("cmd-x", principal));
+ assertEquals("COMMAND_NOT_FOUND", ex.getErrorCode());
+ }
+
+ private void stubPreflight(String preflightHash) {
+ when(preflightService.preflight(any(), any())).thenReturn(preflight(preflightHash));
+ }
+
+ private static MdmAgentImportPreflightRespVO preflight(String hash) {
+ return MdmAgentImportPreflightRespVO.builder()
+ .preflightHash(hash)
+ .canCommit(true)
+ .rows(List.of(MdmAgentImportPreflightRespVO.Row.builder()
+ .candidateId("c-0").action("CREATE").build()))
+ .summary(MdmAgentImportPreflightRespVO.Summary.builder()
+ .total(1).create(1).skip(0).blocked(0).build())
+ .build();
+ }
+
+ private AtomicReference<MdmAgentImportCommandDO> captureInsertedCommand() {
+ AtomicReference<MdmAgentImportCommandDO> holder = new AtomicReference<>();
+ doAnswer(invocation -> {
+ MdmAgentImportCommandDO command = invocation.getArgument(0);
+ command.setId(1L);
+ holder.set(command);
+ return 1;
+ }).when(commandMapper).insert(any(MdmAgentImportCommandDO.class));
+ return holder;
+ }
+
+ private static MdmAgentImportCommitReqVO request(String name) {
+ MdmAgentImportPreflightReqVO.Row row = new MdmAgentImportPreflightReqVO.Row();
+ row.setCandidateId("c-0");
+ row.setRowNo(1);
+ row.setCode("AGENT-E2E-1");
+ row.setName(name);
+ row.setCategoryCode("RAW");
+ row.setUnitMeasureCode("PCS");
+
+ MdmAgentImportCommitReqVO reqVO = new MdmAgentImportCommitReqVO();
+ reqVO.setCommandId("cmd-1");
+ reqVO.setIdempotencyKey("idem-1");
+ reqVO.setAttachmentId(5L);
+ reqVO.setSessionId(21L);
+ reqVO.setSourceSha256(SOURCE_SHA);
+ reqVO.setPreflightHash(PREFLIGHT_HASH);
+ reqVO.setProposalRevision("rev-1");
+ reqVO.setRows(List.of(row));
+ return reqVO;
+ }
+}
--
Gitblit v1.9.3