diff --git a/nflg-qms-admin/src/test/java/com/nflg/qms/admin/QmsQcMaterialApiTest.java b/nflg-qms-admin/src/test/java/com/nflg/qms/admin/QmsQcMaterialApiTest.java
new file mode 100644
index 00000000..656884c7
--- /dev/null
+++ b/nflg-qms-admin/src/test/java/com/nflg/qms/admin/QmsQcMaterialApiTest.java
@@ -0,0 +1,378 @@
+package com.nflg.qms.admin;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONUtil;
+import com.nflg.wms.common.pojo.ApiResult;
+import com.nflg.wms.common.pojo.PageData;
+import com.nflg.wms.common.pojo.qo.QmsQcMaterialAddQO;
+import com.nflg.wms.common.pojo.qo.QmsQcMaterialSearchQO;
+import com.nflg.wms.common.pojo.qo.QmsQcMaterialUpdateQO;
+import com.nflg.wms.common.pojo.vo.QmsQcMaterialVO;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * QMS 质检物料模块接口测试
+ *
+ * 测试前提:
+ * 1. qms-admin 服务已启动(默认 http://localhost:8105)
+ * 2. 测试账号已登录,将有效的 token 填入 TOKEN 常量
+ * 3. 数据库中已存在物料类别编码,修改 MATERIAL_CATEGORY_CODE 为有效的类别编码
+ *
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class QmsQcMaterialApiTest {
+
+ // ===================== 配置区 =====================
+ /** 服务地址 */
+ private static final String BASE_URL = "http://localhost:8105";
+ /** 当前登录用户的 token */
+ private static final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjEsInJuU3RyIjoidVFwSWM2R3RJeUoxcFNSczBadzJzb1hvMUZLZXB3czkiLCJuYW1lIjoi6LaF57qn566h55CG5ZGYIiwiY29kZSI6ImFkbWluIiwicm9sZXMiOlsiU3VwZXJBZG1pbiJdLCJ0eXBlIjoxfQ.FtQ2uVwvuxsjAFbXnB006hV1pODtRhZT0z_9nfuR0So";
+ /** 物料类别编码(需要根据实际数据库中的有效值修改) */
+ private static final String MATERIAL_CATEGORY_CODE = "CAT001";
+ // ===================== 配置区结束 =====================
+
+ /** 测试过程中创建的物料编号 */
+ private static String createdMaterialNo;
+
+ // ==================== HTTP 工具方法 ====================
+
+ private static ApiResult post(String path, Object body, TypeReference> typeRef) {
+ String url = BASE_URL + path;
+ String reqBody = body == null ? "" : JSONUtil.toJsonStr(body);
+ HttpResponse resp = HttpRequest.post(url)
+ .header("authorization", TOKEN)
+ .header("Content-Type", "application/json")
+ .body(reqBody)
+ .execute();
+ String raw = resp.body();
+ System.out.println("[POST] " + path);
+ System.out.println(" 请求: " + reqBody);
+ System.out.println(" 响应: " + raw);
+ return JSONUtil.toBean(raw, typeRef, false);
+ }
+
+ private static void assertSuccess(ApiResult result, String msg) {
+ Assert.isTrue(result != null && result.getCode() == 200,
+ () -> new RuntimeException(msg + " => " + JSONUtil.toJsonStr(result)));
+ }
+
+ private static void assertFailed(ApiResult> result, String msg) {
+ Assert.isTrue(result != null && result.getCode() != 200,
+ () -> new RuntimeException(msg + " => 预期失败但实际成功"));
+ }
+
+ // ==================== 新增接口测试 ====================
+
+ /**
+ * 【新增质检物料】正常新增
+ * 验证点:接口返回成功
+ */
+ @Test
+ @Order(1)
+ public void test01_addMaterial_Success() {
+ QmsQcMaterialAddQO request = buildValidAddRequest();
+
+ ApiResult result = post("/qcMaterial/add", request, new TypeReference<>() {});
+ assertSuccess(result, "新增质检物料失败");
+ System.out.println(" ✅ 新增质检物料成功");
+
+ createdMaterialNo = request.getMaterialNo();
+ }
+
+ /**
+ * 【新增质检物料】物料编号为空
+ * 验证点:接口返回参数校验错误
+ */
+ @Test
+ @Order(2)
+ public void test02_addMaterial_MaterialNoBlank() {
+ QmsQcMaterialAddQO request = buildValidAddRequest();
+ request.setMaterialNo(null);
+
+ ApiResult result = post("/qcMaterial/add", request, new TypeReference<>() {});
+ assertFailed(result, "物料编号为空应返回失败");
+ System.out.println(" ✅ 物料编号为空校验通过");
+ }
+
+ /**
+ * 【新增质检物料】物料类别编码为空
+ * 验证点:接口返回参数校验错误
+ */
+ @Test
+ @Order(3)
+ public void test03_addMaterial_CategoryCodeBlank() {
+ QmsQcMaterialAddQO request = buildValidAddRequest();
+ request.setMaterialCategoryCode(null);
+
+ ApiResult result = post("/qcMaterial/add", request, new TypeReference<>() {});
+ assertFailed(result, "物料类别编码为空应返回失败");
+ System.out.println(" ✅ 物料类别编码为空校验通过");
+ }
+
+ /**
+ * 【新增质检物料】物料类别不存在
+ * 验证点:接口返回业务错误
+ */
+ @Test
+ @Order(4)
+ public void test04_addMaterial_CategoryNotExist() {
+ QmsQcMaterialAddQO request = buildValidAddRequest();
+ request.setMaterialCategoryCode("INVALID_CATEGORY_999");
+
+ ApiResult result = post("/qcMaterial/add", request, new TypeReference<>() {});
+ assertFailed(result, "物料类别不存在应返回失败");
+ System.out.println(" ✅ 物料类别不存在校验通过");
+ }
+
+ /**
+ * 【新增质检物料】完整参数场景
+ * 验证点:所有字段都填充时能正常处理
+ */
+ @Test
+ @Order(5)
+ public void test05_addMaterial_FullFields() {
+ QmsQcMaterialAddQO request = buildValidAddRequest();
+ request.setMaterialNo("TEST_FULL_" + System.currentTimeMillis());
+ request.setMaterialDesc("完整参数测试物料");
+ request.setMaterialDescIsUpgrade(true);
+ request.setDrawingNo("DWG-TEST-001");
+ request.setDrawingNoVer("V1.0");
+ request.setMaterialName("测试物料名称");
+ request.setMaterialTexture("钢材");
+ request.setMaterialSpecifications("100x50x10");
+ request.setIsStandardMaintained(false);
+
+ ApiResult result = post("/qcMaterial/add", request, new TypeReference<>() {});
+ assertSuccess(result, "完整参数新增失败");
+ System.out.println(" ✅ 完整参数新增成功");
+ }
+
+ // ==================== 编辑接口测试 ====================
+
+ /**
+ * 【编辑质检物料】正常编辑
+ * 验证点:接口返回成功
+ */
+ @Test
+ @Order(6)
+ public void test06_updateMaterial_Success() {
+ // 先新增一个物料用于编辑
+ QmsQcMaterialAddQO addRequest = buildValidAddRequest();
+ addRequest.setMaterialNo("TEST_UPDATE_" + System.currentTimeMillis());
+ addRequest.setMaterialName("待编辑物料");
+ post("/qcMaterial/add", addRequest, new TypeReference<>() {});
+
+ // 搜索获取新增的物料ID
+ QmsQcMaterialSearchQO searchRequest = new QmsQcMaterialSearchQO();
+ searchRequest.setMaterialNo(addRequest.getMaterialNo());
+ ApiResult> searchResult = post("/qcMaterial/search", searchRequest, new TypeReference<>() {});
+ assertSuccess(searchResult, "搜索物料失败");
+
+ Long materialId = searchResult.getResult().getItems().get(0).getId();
+
+ // 编辑物料
+ QmsQcMaterialUpdateQO updateRequest = new QmsQcMaterialUpdateQO();
+ updateRequest.setId(materialId);
+ updateRequest.setMaterialName("已编辑物料");
+ updateRequest.setMaterialDesc("编辑后的描述");
+
+ ApiResult result = post("/qcMaterial/update", updateRequest, new TypeReference<>() {});
+ assertSuccess(result, "编辑质检物料失败");
+ System.out.println(" ✅ 编辑质检物料成功");
+ }
+
+ /**
+ * 【编辑质检物料】物料ID为空
+ * 验证点:接口返回参数校验错误
+ */
+ @Test
+ @Order(7)
+ public void test07_updateMaterial_IdNull() {
+ QmsQcMaterialUpdateQO request = new QmsQcMaterialUpdateQO();
+ request.setId(null);
+ request.setMaterialName("测试");
+
+ ApiResult result = post("/qcMaterial/update", request, new TypeReference<>() {});
+ assertFailed(result, "物料ID为空应返回失败");
+ System.out.println(" ✅ 物料ID为空校验通过");
+ }
+
+ /**
+ * 【编辑质检物料】物料不存在
+ * 验证点:接口返回业务错误
+ */
+ @Test
+ @Order(8)
+ public void test08_updateMaterial_NotExist() {
+ QmsQcMaterialUpdateQO request = new QmsQcMaterialUpdateQO();
+ request.setId(999999999L);
+ request.setMaterialName("测试");
+
+ ApiResult result = post("/qcMaterial/update", request, new TypeReference<>() {});
+ assertFailed(result, "物料不存在应返回失败");
+ System.out.println(" ✅ 物料不存在校验通过");
+ }
+
+ // ==================== 删除接口测试 ====================
+
+ /**
+ * 【删除质检物料】正常删除(规则未维护)
+ * 验证点:接口返回成功
+ */
+ @Test
+ @Order(9)
+ public void test09_deleteMaterial_Success() {
+ // 先新增一个物料用于删除
+ QmsQcMaterialAddQO addRequest = buildValidAddRequest();
+ addRequest.setMaterialNo("TEST_DELETE_" + System.currentTimeMillis());
+ addRequest.setIsStandardMaintained(false);
+ post("/qcMaterial/add", addRequest, new TypeReference<>() {});
+
+ // 搜索获取新增的物料ID
+ QmsQcMaterialSearchQO searchRequest = new QmsQcMaterialSearchQO();
+ searchRequest.setMaterialNo(addRequest.getMaterialNo());
+ ApiResult> searchResult = post("/qcMaterial/search", searchRequest, new TypeReference<>() {});
+ assertSuccess(searchResult, "搜索物料失败");
+
+ Long materialId = searchResult.getResult().getItems().get(0).getId();
+
+ // 删除物料
+ ApiResult result = post("/qcMaterial/delete?id=" + materialId, null, new TypeReference<>() {});
+ assertSuccess(result, "删除质检物料失败");
+ System.out.println(" ✅ 删除质检物料成功");
+ }
+
+ /**
+ * 【删除质检物料】规则已维护不允许删除
+ * 验证点:接口返回业务错误
+ */
+ @Test
+ @Order(10)
+ public void test10_deleteMaterial_StandardMaintained() {
+ // 先新增一个规则已维护的物料
+ QmsQcMaterialAddQO addRequest = buildValidAddRequest();
+ addRequest.setMaterialNo("TEST_DELETE_MAINTAINED_" + System.currentTimeMillis());
+ addRequest.setIsStandardMaintained(true);
+ post("/qcMaterial/add", addRequest, new TypeReference<>() {});
+
+ // 搜索获取新增的物料ID
+ QmsQcMaterialSearchQO searchRequest = new QmsQcMaterialSearchQO();
+ searchRequest.setMaterialNo(addRequest.getMaterialNo());
+ ApiResult> searchResult = post("/qcMaterial/search", searchRequest, new TypeReference<>() {});
+ assertSuccess(searchResult, "搜索物料失败");
+
+ Long materialId = searchResult.getResult().getItems().get(0).getId();
+
+ // 尝试删除
+ ApiResult result = post("/qcMaterial/delete?id=" + materialId, null, new TypeReference<>() {});
+ assertFailed(result, "规则已维护应不允许删除");
+ System.out.println(" ✅ 规则已维护不允许删除校验通过");
+ }
+
+ /**
+ * 【删除质检物料】物料不存在
+ * 验证点:接口返回业务错误
+ */
+ @Test
+ @Order(11)
+ public void test11_deleteMaterial_NotExist() {
+ ApiResult result = post("/qcMaterial/delete?id=999999999", null, new TypeReference<>() {});
+ assertFailed(result, "物料不存在应返回失败");
+ System.out.println(" ✅ 物料不存在校验通过");
+ }
+
+ // ==================== 搜索接口测试 ====================
+
+ /**
+ * 【搜索质检物料】正常搜索
+ * 验证点:返回分页数据
+ */
+ @Test
+ @Order(12)
+ public void test12_searchMaterial_Success() {
+ QmsQcMaterialSearchQO request = new QmsQcMaterialSearchQO();
+ request.setPage(1);
+ request.setPageSize(10);
+
+ ApiResult> result = post("/qcMaterial/search", request, new TypeReference<>() {});
+ assertSuccess(result, "搜索质检物料失败");
+ System.out.println(" ✅ 搜索成功,总数: " + result.getResult().getTotal());
+ }
+
+ /**
+ * 【搜索质检物料】按物料编号模糊搜索
+ * 验证点:返回匹配的物料
+ */
+ @Test
+ @Order(13)
+ public void test13_searchMaterial_ByMaterialNo() {
+ QmsQcMaterialSearchQO request = new QmsQcMaterialSearchQO();
+ request.setPage(1);
+ request.setPageSize(10);
+ request.setMaterialNo("TEST");
+
+ ApiResult> result = post("/qcMaterial/search", request, new TypeReference<>() {});
+ assertSuccess(result, "按物料编号搜索失败");
+ System.out.println(" ✅ 按物料编号搜索成功,匹配数: " + result.getResult().getTotal());
+ }
+
+ /**
+ * 【搜索质检物料】按物料类别搜索
+ * 验证点:返回指定类别的物料
+ */
+ @Test
+ @Order(14)
+ public void test14_searchMaterial_ByCategory() {
+ QmsQcMaterialSearchQO request = new QmsQcMaterialSearchQO();
+ request.setPage(1);
+ request.setPageSize(10);
+ request.setMaterialCategoryCode(MATERIAL_CATEGORY_CODE);
+
+ ApiResult> result = post("/qcMaterial/search", request, new TypeReference<>() {});
+ assertSuccess(result, "按物料类别搜索失败");
+ System.out.println(" ✅ 按物料类别搜索成功,匹配数: " + result.getResult().getTotal());
+ }
+
+ /**
+ * 【搜索质检物料】按物料名称模糊搜索
+ * 验证点:返回匹配的物料
+ */
+ @Test
+ @Order(15)
+ public void test15_searchMaterial_ByMaterialName() {
+ QmsQcMaterialSearchQO request = new QmsQcMaterialSearchQO();
+ request.setPage(1);
+ request.setPageSize(10);
+ request.setMaterialName("测试");
+
+ ApiResult> result = post("/qcMaterial/search", request, new TypeReference<>() {});
+ assertSuccess(result, "按物料名称搜索失败");
+ System.out.println(" ✅ 按物料名称搜索成功,匹配数: " + result.getResult().getTotal());
+ }
+
+ // ==================== 辅助方法 ====================
+
+ /**
+ * 构建一个完整的有效新增请求参数
+ */
+ private QmsQcMaterialAddQO buildValidAddRequest() {
+ QmsQcMaterialAddQO request = new QmsQcMaterialAddQO();
+ request.setMaterialNo("TEST_" + System.currentTimeMillis());
+ request.setMaterialDesc("接口测试物料");
+ request.setMaterialCategoryCode(MATERIAL_CATEGORY_CODE);
+ request.setMaterialName("测试物料");
+ request.setDrawingNo("DWG-" + System.currentTimeMillis());
+ request.setDrawingNoVer("V1.0");
+ request.setIsStandardMaintained(false);
+ return request;
+ }
+}