liu
2 天以前 43aab58c9ecb1203770ba382efbdbae299ca87ec
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/md/item/MesBomImportAdapterTest.java
对比新文件
@@ -0,0 +1,174 @@
package cn.iocoder.yudao.module.mes.service.md.item;
import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO;
import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductBomMapper;
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportCommitReqVO;
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightReqVO;
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightRespVO;
import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportRowReceipt;
import cn.iocoder.yudao.module.system.framework.agent.AgentPrincipal;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
class MesBomImportAdapterTest {
    private static final AgentPrincipal PRINCIPAL = new AgentPrincipal(1L, "live");
    private MesBomImportAdapter adapter;
    private MesMdItemService itemService;
    private MesMdProductBomService productBomService;
    private MesMdProductBomMapper productBomMapper;
    @BeforeEach
    void setUp() {
        adapter = new MesBomImportAdapter();
        itemService = mock(MesMdItemService.class);
        productBomService = mock(MesMdProductBomService.class);
        productBomMapper = mock(MesMdProductBomMapper.class);
        ReflectionTestUtils.setField(adapter, "itemService", itemService);
        ReflectionTestUtils.setField(adapter, "productBomService", productBomService);
        ReflectionTestUtils.setField(adapter, "productBomMapper", productBomMapper);
        when(itemService.getItemByCode("P")).thenReturn(item(1L, "P"));
        when(itemService.getItemByCode("C")).thenReturn(item(2L, "C"));
        when(itemService.getItemByCode("A")).thenReturn(item(3L, "A"));
        when(itemService.getItemByCode("X")).thenReturn(null);
        when(productBomMapper.selectAll()).thenReturn(List.of());
    }
    @Test
    void preflightCreatesWhenItemsAreSynced() {
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2")));
        assertEquals("CREATE", plan.getRows().get(0).getAction());
        assertEquals(1, plan.getSummary().getCreate());
        assertTrue(plan.getCanCommit());
        assertNotNull(plan.getPreflightHash());
    }
    @Test
    void existingCombinationIsSkippedWithWarning() {
        when(productBomMapper.selectAll()).thenReturn(List.of(bom(50L, 1L, 2L)));
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2")));
        assertEquals("SKIP", plan.getRows().get(0).getAction());
        assertEquals(50L, plan.getRows().get(0).getTargetId());
        assertEquals(1, plan.getSummary().getSkip());
        assertTrue(plan.getRows().get(0).getWarnings().stream()
                .anyMatch(item -> "BOM_EXISTS".equals(item.getCode())));
    }
    @Test
    void unsyncedComponentBlocksRow() {
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "X", "1")));
        assertEquals("BLOCKED", plan.getRows().get(0).getAction());
        assertTrue(plan.getRows().get(0).getBlockers().stream()
                .anyMatch(item -> "MES_ITEM_NOT_SYNCED".equals(item.getCode())));
        assertFalse(plan.getCanCommit());
    }
    @Test
    void selfReferenceBlocksRow() {
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "P", "1")));
        assertEquals("BLOCKED", plan.getRows().get(0).getAction());
        assertTrue(plan.getRows().get(0).getBlockers().stream()
                .anyMatch(item -> "BOM_SELF_REFERENCE".equals(item.getCode())));
    }
    @Test
    void duplicateCombinationInFileBlocksSecondRow() {
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(
                row("r1", "P", "C", "1"),
                row("r2", "P", "C", "2")));
        assertEquals("CREATE", plan.getRows().get(0).getAction());
        assertEquals("BLOCKED", plan.getRows().get(1).getAction());
        assertTrue(plan.getRows().get(1).getBlockers().stream()
                .anyMatch(item -> "DUPLICATE_IN_FILE".equals(item.getCode())));
    }
    @Test
    void cycleAgainstExistingGraphBlocksRow() {
        when(productBomMapper.selectAll()).thenReturn(List.of(bom(60L, 3L, 1L)));
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "A", "1")));
        assertEquals("BLOCKED", plan.getRows().get(0).getAction());
        assertTrue(plan.getRows().get(0).getBlockers().stream()
                .anyMatch(item -> "BOM_CYCLE".equals(item.getCode())));
    }
    @Test
    void invalidQuantityBlocksRow() {
        AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "0")));
        assertEquals("BLOCKED", plan.getRows().get(0).getAction());
        assertTrue(plan.getRows().get(0).getBlockers().stream()
                .anyMatch(item -> "INVALID_QUANTITY".equals(item.getCode())));
    }
    @Test
    void commitCreatesBomWithResolvedItemIds() {
        when(productBomService.createProductBom(any())).thenReturn(88L);
        AgentImportRowReceipt receipt = adapter.commitRow(PRINCIPAL, new AgentImportCommitReqVO(),
                AgentImportPreflightRespVO.Row.builder().candidateId("r1").action("CREATE").build(),
                row("r1", "P", "C", "2"));
        assertEquals(88L, receipt.targetId());
        assertEquals("P", receipt.code());
        verify(productBomService).createProductBom(any(MesMdProductBomSaveReqVO.class));
    }
    private static MesMdItemDO item(Long id, String code) {
        MesMdItemDO item = new MesMdItemDO();
        item.setId(id);
        item.setCode(code);
        return item;
    }
    private static MesMdProductBomDO bom(Long id, Long itemId, Long bomItemId) {
        MesMdProductBomDO bom = new MesMdProductBomDO();
        bom.setId(id);
        bom.setItemId(itemId);
        bom.setBomItemId(bomItemId);
        bom.setQuantity(BigDecimal.ONE);
        return bom;
    }
    private static AgentImportPreflightReqVO request(AgentImportPreflightReqVO.Row... rows) {
        AgentImportPreflightReqVO request = new AgentImportPreflightReqVO();
        request.setAttachmentId(1L);
        request.setSourceSha256("a".repeat(64));
        request.setProposalRevision("0");
        request.setRows(List.of(rows));
        return request;
    }
    private static AgentImportPreflightReqVO.Row row(String candidateId, String parent, String component,
                                                      String quantity) {
        Map<String, String> values = new LinkedHashMap<>();
        values.put("parentCode", parent);
        values.put("componentCode", component);
        values.put("quantity", quantity);
        AgentImportPreflightReqVO.Row row = new AgentImportPreflightReqVO.Row();
        row.setCandidateId(candidateId);
        row.setRowNo(1);
        row.setValues(values);
        return row;
    }
}