mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
1、贴皮管理部分更新方法回调类型修正;2、新增exec服务单元测试配置;3增贴皮管理service、controller单元测试完善;
This commit is contained in:
+7
-4
@@ -104,16 +104,18 @@ public class VeneerController {
|
||||
@PutMapping("")
|
||||
@Operation(summary = "编辑贴皮")
|
||||
public CommonResult<Boolean> updateVeneer(@Valid @RequestBody VeneerSaveReqVO reqVO) {
|
||||
return success(veneerService.update(reqVO) == 1);
|
||||
veneerService.update(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "删除贴皮")
|
||||
public CommonResult<Boolean> deleteVeneer(@PathVariable Long id) {
|
||||
return success(veneerService.delete(id) == 1);
|
||||
veneerService.delete(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/pic")
|
||||
@PostMapping("/pic")
|
||||
@Operation(summary = "上传贴皮照片")
|
||||
@OperateLog(logArgs = false, type = CREATE)
|
||||
public CommonResult<Long> uploadVeneerPic(@RequestPart(value = "file") MultipartFile file) throws IOException {
|
||||
@@ -123,6 +125,7 @@ public class VeneerController {
|
||||
@PostMapping("/defect")
|
||||
@Operation(summary = "保存瑕疵数据")
|
||||
public CommonResult<Boolean> saveDefect(@Valid @RequestBody VeneerDefectSaveReqVO reqVO) {
|
||||
return success(veneerService.saveDefect(reqVO) == 1);
|
||||
veneerService.saveDefect(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ public interface VeneerService {
|
||||
* @param reqVO
|
||||
* @return
|
||||
*/
|
||||
int update(VeneerSaveReqVO reqVO);
|
||||
void update(VeneerSaveReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 删除贴皮
|
||||
@@ -42,7 +42,7 @@ public interface VeneerService {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
int delete(Long id);
|
||||
void delete(Long id);
|
||||
|
||||
/**
|
||||
* 上传贴皮照片
|
||||
@@ -95,5 +95,5 @@ public interface VeneerService {
|
||||
* @param defectSaveReqVO
|
||||
* @return
|
||||
*/
|
||||
int saveDefect(VeneerDefectSaveReqVO defectSaveReqVO);
|
||||
void saveDefect(VeneerDefectSaveReqVO defectSaveReqVO);
|
||||
}
|
||||
|
||||
+14
-19
@@ -31,6 +31,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;
|
||||
@@ -73,7 +74,7 @@ public class VeneerServiceImpl implements VeneerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(VeneerSaveReqVO reqVO) {
|
||||
public void update(VeneerSaveReqVO reqVO) {
|
||||
Long id = reqVO.getId();
|
||||
|
||||
// 1、校验贴皮是否存在
|
||||
@@ -90,18 +91,18 @@ public class VeneerServiceImpl implements VeneerService {
|
||||
|
||||
//3、贴皮数据入库
|
||||
VeneerDO veneerDO = BeanUtil.copyProperties(reqVO, VeneerDO.class);
|
||||
return veneerMapper.updateById(veneerDO);
|
||||
veneerMapper.updateById(veneerDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Long id) {
|
||||
public void delete(Long id) {
|
||||
// 1、校验贴皮是否存在
|
||||
if (ObjectUtil.isNull(validateExist(id))) {
|
||||
throw new ServiceException(VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
//2、删除贴皮
|
||||
return veneerMapper.deleteById(id);
|
||||
veneerMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,7 +162,7 @@ public class VeneerServiceImpl implements VeneerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int saveDefect(VeneerDefectSaveReqVO defectSaveReqVO) {
|
||||
public void saveDefect(VeneerDefectSaveReqVO defectSaveReqVO) {
|
||||
Long id = defectSaveReqVO.getId();
|
||||
// 校验贴皮是否存在
|
||||
if (ObjectUtil.isNull(validateExist(id))) {
|
||||
@@ -171,12 +172,11 @@ public class VeneerServiceImpl implements VeneerService {
|
||||
String defectData = defectSaveReqVO.getDefectData();
|
||||
if(StringUtils.isNotEmpty(defectData)) {
|
||||
// 更新瑕疵数据和状态
|
||||
return veneerMapper.update(new LambdaUpdateWrapper<VeneerDO>()
|
||||
veneerMapper.update(new LambdaUpdateWrapper<VeneerDO>()
|
||||
.eq(VeneerDO::getId, id)
|
||||
.set(VeneerDO::getDefect, true)
|
||||
.set(VeneerDO::getDefectData, JsonUtils.zipString(defectData)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,17 +209,12 @@ public class VeneerServiceImpl implements VeneerService {
|
||||
* @return
|
||||
*/
|
||||
public static String getFileExtension(String fileName) {
|
||||
if (StringUtils.isEmpty(fileName)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int lastDotIndex = fileName.lastIndexOf('.');
|
||||
if (lastDotIndex < 0 || lastDotIndex == fileName.length() - 1) {
|
||||
// 没有点号,或者点号在最后一位(例如 "file.")
|
||||
return "";
|
||||
}
|
||||
|
||||
// 截取后缀部分并转小写
|
||||
return "." + fileName.substring(lastDotIndex + 1).toLowerCase(Locale.ROOT);
|
||||
return Optional.ofNullable(fileName)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.filter(name -> name.contains("."))
|
||||
.map(name -> name.substring(name.lastIndexOf('.')))
|
||||
.filter(ext -> ext.length() > 1)
|
||||
.map(ext -> ext.toLowerCase(Locale.ROOT))
|
||||
.orElse(".jpg");
|
||||
}
|
||||
}
|
||||
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
package com.cf.imes.module.executor.controller.admin.veneer;
|
||||
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.security.test.WithMockLoginUser;
|
||||
import com.cf.imes.framework.test.core.ut.BaseWebUnitTest;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO;
|
||||
import com.cf.imes.module.executor.enums.veneer.VeneerProductLevelEnum;
|
||||
import com.cf.imes.module.executor.service.veneer.VeneerService;
|
||||
import com.cf.imes.module.executor.util.file.FileHelperUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* 贴皮管理controller 单元测试
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2026/1/7 16:58
|
||||
*/
|
||||
@WebMvcTest(controllers = VeneerController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
|
||||
class VeneerControllerTest extends BaseWebUnitTest {
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockitoBean
|
||||
private VeneerService veneerService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
void getVeneerPage_success() throws Exception {
|
||||
PageResult<VeneerRespVO> page = new PageResult<>();
|
||||
page.setTotal(0L);
|
||||
page.setList(Collections.emptyList());
|
||||
|
||||
when(veneerService.getPage(any())).thenReturn(page);
|
||||
|
||||
mockMvc.perform(get("/executor/veneer/page"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportVeneerPage_success() throws Exception {
|
||||
// mock service 返回
|
||||
PageResult<VeneerRespVO> page = new PageResult<>();
|
||||
page.setList(Collections.emptyList());
|
||||
page.setTotal(0L);
|
||||
|
||||
when(veneerService.getPage(any())).thenReturn(page);
|
||||
|
||||
mockMvc.perform(get("/executor/veneer/export"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getVeneer_success() throws Exception {
|
||||
VeneerRespVO resp = new VeneerRespVO();
|
||||
resp.setId(1L);
|
||||
|
||||
when(veneerService.get(1L)).thenReturn(resp);
|
||||
|
||||
mockMvc.perform(get("/executor/veneer/1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data.id").value(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createVeneer_success() throws Exception {
|
||||
// 准备参数
|
||||
VeneerSaveReqVO veneerSaveReqVO = new VeneerSaveReqVO();
|
||||
veneerSaveReqVO.setVeneerNo("SP14126");
|
||||
veneerSaveReqVO.setClassificationName("分类名称");
|
||||
veneerSaveReqVO.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerSaveReqVO.setVeneerName("贴皮名称");
|
||||
veneerSaveReqVO.setNum(1);
|
||||
veneerSaveReqVO.setWidth(new BigDecimal(10));
|
||||
veneerSaveReqVO.setLength(new BigDecimal(20));
|
||||
veneerSaveReqVO.setThickness(new BigDecimal(30));
|
||||
|
||||
when(veneerService.create(any())).thenReturn(1L);
|
||||
|
||||
mockMvc.perform(post("/executor/veneer")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(veneerSaveReqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateVeneer_success() throws Exception {
|
||||
// 准备参数
|
||||
VeneerSaveReqVO veneerSaveReqVO = new VeneerSaveReqVO();
|
||||
veneerSaveReqVO.setId(999l);
|
||||
veneerSaveReqVO.setVeneerNo("SP14126");
|
||||
veneerSaveReqVO.setClassificationName("分类名称");
|
||||
veneerSaveReqVO.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerSaveReqVO.setVeneerName("贴皮名称");
|
||||
veneerSaveReqVO.setNum(1);
|
||||
veneerSaveReqVO.setWidth(new BigDecimal(10));
|
||||
veneerSaveReqVO.setLength(new BigDecimal(20));
|
||||
veneerSaveReqVO.setThickness(new BigDecimal(30));
|
||||
|
||||
doNothing().when(veneerService).update(any());
|
||||
|
||||
mockMvc.perform(put("/executor/veneer")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(veneerSaveReqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteVeneer_success() throws Exception {
|
||||
doNothing().when(veneerService).delete(1L);
|
||||
|
||||
mockMvc.perform(delete("/executor/veneer/1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadVeneerPic_success() throws Exception {
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
"file", "a.jpg", "image/jpeg", "123".getBytes()
|
||||
);
|
||||
|
||||
when(veneerService.uploadPic(any())).thenReturn(10L);
|
||||
|
||||
mockMvc.perform(multipart("/executor/veneer/pic")
|
||||
.file(file))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(10L));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser
|
||||
void importExcel_success() throws Exception {
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
"file", "test.xlsx",
|
||||
"application/vnd.ms-excel",
|
||||
new byte[]{1, 2, 3}
|
||||
);
|
||||
|
||||
mockMvc.perform(multipart("/executor/veneer/import").file(file))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getVeneerImportTemplate_success() throws Exception {
|
||||
try (MockedStatic<FileHelperUtil> mocked =
|
||||
Mockito.mockStatic(FileHelperUtil.class)) {
|
||||
|
||||
mocked.when(() ->
|
||||
FileHelperUtil.getFirstFile(
|
||||
anyString(),
|
||||
any(HttpServletResponse.class))
|
||||
).thenAnswer(invocation -> null);
|
||||
|
||||
mockMvc.perform(get("/executor/veneer/import/template"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveDefect_success() throws Exception {
|
||||
VeneerDefectSaveReqVO reqVO = new VeneerDefectSaveReqVO();
|
||||
reqVO.setId(1L);
|
||||
|
||||
doNothing().when(veneerService).saveDefect(any());
|
||||
|
||||
mockMvc.perform(post("/executor/veneer/defect")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(reqVO)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.data").value(true));
|
||||
}
|
||||
|
||||
}
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
package com.cf.imes.module.executor.service.veneer;
|
||||
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.json.JsonUtils;
|
||||
import com.cf.imes.framework.security.test.WithMockLoginUser;
|
||||
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerDefectSaveReqVO;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerPageReqVO;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.veneer.vo.VeneerSaveReqVO;
|
||||
import com.cf.imes.module.executor.dal.dataobject.veneer.VeneerDO;
|
||||
import com.cf.imes.module.executor.dal.mysql.veneer.VeneerMapper;
|
||||
import com.cf.imes.module.executor.enums.veneer.VeneerProductLevelEnum;
|
||||
import com.cf.imes.module.infra.api.file.FileApi;
|
||||
import com.cf.imes.module.system.api.organ.OrganApi;
|
||||
import com.cf.imes.module.system.api.organ.dto.OrganizationDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NOT_EXIST;
|
||||
import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NO_EXIST;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
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.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Gqr
|
||||
* @since 2026/1/7 15:08
|
||||
*/
|
||||
@Import(VeneerServiceImpl.class)
|
||||
class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
@Resource
|
||||
private VeneerServiceImpl veneerService;
|
||||
|
||||
@MockitoBean
|
||||
private FileApi fileApi;
|
||||
|
||||
@MockitoBean
|
||||
private OrganApi organApi;
|
||||
|
||||
@Resource
|
||||
private VeneerMapper veneerMapper;
|
||||
|
||||
@Test
|
||||
void create_success_when_veneer_no_not_exists() {
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setVeneerNo("VN-001");
|
||||
reqVO.setClassificationName("测试分类");
|
||||
reqVO.setVeneerName("测试贴皮");
|
||||
reqVO.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
|
||||
Long id = veneerService.create(reqVO);
|
||||
|
||||
assertNotNull(id);
|
||||
|
||||
VeneerDO db = veneerMapper.selectById(id);
|
||||
assertEquals("VN-001", db.getVeneerNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void create_fail_when_veneer_no_exists() {
|
||||
// 先插一条
|
||||
VeneerDO exist = new VeneerDO();
|
||||
exist.setVeneerNo("VN-002");
|
||||
exist.setClassificationName("分类");
|
||||
exist.setVeneerName("贴皮");
|
||||
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerMapper.insert(exist);
|
||||
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setVeneerNo("VN-002");
|
||||
|
||||
assertServiceException(() -> veneerService.create(reqVO),
|
||||
VENEER_NO_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_success_when_same_veneer_no() {
|
||||
VeneerDO exist = new VeneerDO();
|
||||
exist.setVeneerNo("VN-100");
|
||||
exist.setClassificationName("分类");
|
||||
exist.setVeneerName("贴皮");
|
||||
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerMapper.insert(exist);
|
||||
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setId(exist.getId());
|
||||
reqVO.setVeneerNo("VN-100"); // 不变
|
||||
reqVO.setClassificationName("新分类");
|
||||
reqVO.setVeneerName("新贴皮");
|
||||
reqVO.setProductLevel(VeneerProductLevelEnum.B.getCode());
|
||||
|
||||
assertDoesNotThrow(() -> veneerService.update(reqVO));
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_fail_when_veneer_no_exists() {
|
||||
VeneerDO v1 = new VeneerDO();
|
||||
v1.setVeneerNo("VN-101");
|
||||
v1.setClassificationName("分类1");
|
||||
v1.setVeneerName("贴皮1");
|
||||
v1.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerMapper.insert(v1);
|
||||
|
||||
VeneerDO v2 = new VeneerDO();
|
||||
v2.setVeneerNo("VN-102");
|
||||
v2.setClassificationName("分类2");
|
||||
v2.setVeneerName("贴皮2");
|
||||
v2.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerMapper.insert(v2);
|
||||
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setId(v2.getId());
|
||||
reqVO.setVeneerNo("VN-101"); // 冲突
|
||||
|
||||
assertServiceException(() -> veneerService.update(reqVO),
|
||||
VENEER_NO_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_fail_when_not_exists() {
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setId(999L);
|
||||
reqVO.setVeneerNo("VN-999");
|
||||
|
||||
assertServiceException(() -> veneerService.update(reqVO),
|
||||
VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_fail_when_id_null(){
|
||||
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
|
||||
reqVO.setId(null);
|
||||
assertServiceException(() -> veneerService.update(reqVO),
|
||||
VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void delete_success() {
|
||||
VeneerDO exist = new VeneerDO();
|
||||
exist.setVeneerNo("VN-200");
|
||||
exist.setClassificationName("分类");
|
||||
exist.setVeneerName("贴皮");
|
||||
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
veneerMapper.insert(exist);
|
||||
|
||||
assertDoesNotThrow(() -> veneerService.delete(exist.getId()));
|
||||
|
||||
assertNull(veneerMapper.selectById(exist.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void delete_fail_when_not_exists() {
|
||||
assertServiceException(() -> veneerService.delete(999L),
|
||||
VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void uploadPic_success() throws Exception {
|
||||
|
||||
// mock organApi
|
||||
OrganizationDTO dto = new OrganizationDTO();
|
||||
dto.setName("测试组织");
|
||||
|
||||
when(organApi.getOrganDetails(1L))
|
||||
.thenReturn(CommonResult.success(dto));
|
||||
|
||||
// mock fileApi
|
||||
when(fileApi.createFileAndReturnId(any(byte[].class), anyString()))
|
||||
.thenReturn(100L);
|
||||
|
||||
// mock 文件
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
"file",
|
||||
"test.png",
|
||||
"image/png",
|
||||
"test-content".getBytes()
|
||||
);
|
||||
|
||||
Long fileId = veneerService.uploadPic(file);
|
||||
|
||||
assertEquals(100L, fileId);
|
||||
|
||||
// 验证 fileApi 调用
|
||||
verify(fileApi).createFileAndReturnId(
|
||||
any(byte[].class),
|
||||
argThat(name -> name.contains("测试组织-veneer-pic-file-"))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockLoginUser(organId = 1L)
|
||||
void uploadPic_fail_when_organ_api_error() {
|
||||
|
||||
when(organApi.getOrganDetails(1L))
|
||||
.thenReturn(CommonResult.error(500, "组织服务异常"));
|
||||
|
||||
MockMultipartFile file = new MockMultipartFile(
|
||||
"file",
|
||||
"test.jpg",
|
||||
"image/jpeg",
|
||||
"content".getBytes()
|
||||
);
|
||||
|
||||
ServiceException ex = assertThrows(
|
||||
ServiceException.class,
|
||||
() -> veneerService.uploadPic(file)
|
||||
);
|
||||
|
||||
assertEquals(500, ex.getCode());
|
||||
assertEquals("组织服务异常", ex.getMessage());
|
||||
|
||||
verify(fileApi, never()).createFileAndReturnId(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPage_success_when_has_data() {
|
||||
VeneerDO exist = new VeneerDO();
|
||||
exist.setVeneerNo("VN-200");
|
||||
exist.setClassificationName("分类");
|
||||
exist.setVeneerName("贴皮名称");
|
||||
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
exist.setRemark("备注");
|
||||
exist.setWidth(new BigDecimal(10));
|
||||
exist.setThickness(new BigDecimal(9));
|
||||
veneerMapper.insert(exist);
|
||||
|
||||
VeneerPageReqVO pageReqVO = new VeneerPageReqVO();
|
||||
pageReqVO.setVeneerNo("VN-200");
|
||||
pageReqVO.setClassificationName("分类");
|
||||
pageReqVO.setVeneerName("贴皮名称");
|
||||
pageReqVO.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
pageReqVO.setWidth(new BigDecimal[]{new BigDecimal(0), new BigDecimal(20)});
|
||||
pageReqVO.setThickness(new BigDecimal[]{new BigDecimal(5)});
|
||||
pageReqVO.setRemark("注");
|
||||
|
||||
PageResult<VeneerRespVO> result =
|
||||
veneerService.getPage(pageReqVO);
|
||||
|
||||
assertEquals(1L, result.getTotal());
|
||||
assertEquals(1, result.getList().size());
|
||||
assertEquals("VN-200", result.getList().get(0).getVeneerNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPage_empty(){
|
||||
VeneerPageReqVO reqVO = new VeneerPageReqVO();
|
||||
PageResult<VeneerRespVO> result = veneerService.getPage(reqVO);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(0L, result.getTotal());
|
||||
}
|
||||
|
||||
@Test
|
||||
void get_success_with_defect_data() {
|
||||
String json = "{\"a\":1}";
|
||||
String zipped = JsonUtils.zipString(json);
|
||||
|
||||
VeneerDO veneer = new VeneerDO();
|
||||
veneer.setVeneerNo("VN-301");
|
||||
veneer.setClassificationName("分类");
|
||||
veneer.setVeneerName("贴皮");
|
||||
veneer.setProductLevel(1);
|
||||
veneer.setDefectData(zipped);
|
||||
veneer.setOrganId(1L);
|
||||
|
||||
veneerMapper.insert(veneer);
|
||||
|
||||
VeneerRespVO respVO = veneerService.get(veneer.getId());
|
||||
|
||||
assertNotNull(respVO);
|
||||
assertEquals("VN-301", respVO.getVeneerNo());
|
||||
assertEquals(json, respVO.getDefectData()); // 已解压
|
||||
}
|
||||
|
||||
@Test
|
||||
void get_success_without_defect_data() {
|
||||
VeneerDO veneer = new VeneerDO();
|
||||
veneer.setVeneerNo("VN-302");
|
||||
veneer.setClassificationName("分类");
|
||||
veneer.setVeneerName("贴皮");
|
||||
veneer.setProductLevel(1);
|
||||
veneer.setOrganId(1L);
|
||||
|
||||
veneerMapper.insert(veneer);
|
||||
|
||||
VeneerRespVO respVO = veneerService.get(veneer.getId());
|
||||
|
||||
assertNotNull(respVO);
|
||||
assertNull(respVO.getDefectData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void get_fail_when_not_exist() {
|
||||
assertServiceException(() -> veneerService.get(999L),
|
||||
VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOrgVeneerNo_empty() {
|
||||
Map<String, Long> map = veneerService.getOrgVeneerNo();
|
||||
assertNotNull(map);
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOrgVeneerNo_success() {
|
||||
VeneerDO v1 = new VeneerDO();
|
||||
v1.setVeneerNo("VN-401");
|
||||
v1.setClassificationName("分类");
|
||||
v1.setVeneerName("贴皮");
|
||||
v1.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
v1.setOrganId(1L);
|
||||
|
||||
VeneerDO v2 = new VeneerDO();
|
||||
v2.setVeneerNo("VN-402");
|
||||
v2.setClassificationName("分类");
|
||||
v2.setVeneerName("贴皮");
|
||||
v2.setProductLevel(VeneerProductLevelEnum.C.getCode());
|
||||
v2.setOrganId(1L);
|
||||
|
||||
veneerMapper.insert(v1);
|
||||
veneerMapper.insert(v2);
|
||||
|
||||
Map<String, Long> map = veneerService.getOrgVeneerNo();
|
||||
|
||||
assertEquals(2, map.size());
|
||||
assertEquals(v1.getId(), map.get("VN-401"));
|
||||
assertEquals(v2.getId(), map.get("VN-402"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void batch_success() {
|
||||
VeneerDO v1 = randomPojo(VeneerDO.class, o -> {
|
||||
o.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
});
|
||||
VeneerDO v2 = randomPojo(VeneerDO.class, o -> {
|
||||
o.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
});
|
||||
List<VeneerDO> list = List.of(
|
||||
v1, v2
|
||||
);
|
||||
|
||||
veneerService.batchInsert(list);
|
||||
|
||||
// 验证数据真的进库了
|
||||
List<VeneerDO> dbList = veneerMapper.selectList();
|
||||
|
||||
assertEquals(2, dbList.size());
|
||||
|
||||
v1.setVeneerName("更新后贴皮名称1");
|
||||
v2.setVeneerName("更新后贴皮名称2");
|
||||
|
||||
veneerService.batchUpdate(List.of(v1, v2));
|
||||
|
||||
VeneerDO db1 = veneerMapper.selectById(v1.getId());
|
||||
VeneerDO db2 = veneerMapper.selectById(v2.getId());
|
||||
|
||||
assertEquals("更新后贴皮名称1", db1.getVeneerName());
|
||||
assertEquals("更新后贴皮名称2", db2.getVeneerName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveDefect_success_whenDefectDataNotEmpty() {
|
||||
String defectJson = "{\"x\":10,\"y\":20}";
|
||||
// 先插入贴皮
|
||||
VeneerDO veneer = randomPojo(VeneerDO.class, o -> {
|
||||
o.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
o.setDefectData(defectJson);
|
||||
});
|
||||
veneerMapper.insert(veneer);
|
||||
|
||||
VeneerDefectSaveReqVO req = new VeneerDefectSaveReqVO();
|
||||
req.setId(veneer.getId());
|
||||
req.setDefectData(defectJson);
|
||||
|
||||
assertDoesNotThrow(() -> veneerService.saveDefect(req));
|
||||
|
||||
// 再查数据库
|
||||
VeneerDO db = veneerMapper.selectById(veneer.getId());
|
||||
|
||||
assertTrue(db.getDefect());
|
||||
assertNotNull(db.getDefectData());
|
||||
assertEquals(defectJson, JsonUtils.unzipString(db.getDefectData()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveDefect_throwException_whenVeneerNotExist() {
|
||||
VeneerDefectSaveReqVO req = new VeneerDefectSaveReqVO();
|
||||
req.setId(99999L);
|
||||
|
||||
assertServiceException(() -> veneerService.saveDefect(req),
|
||||
VENEER_NOT_EXIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveDefect_doNothing_whenDefectDataEmpty() {
|
||||
// 先插入贴皮
|
||||
VeneerDO veneer = randomPojo(VeneerDO.class, o -> {
|
||||
o.setProductLevel(VeneerProductLevelEnum.A.getCode());
|
||||
o.setDefectData(null);
|
||||
o.setDefect(false);
|
||||
});
|
||||
veneerMapper.insert(veneer);
|
||||
|
||||
VeneerDefectSaveReqVO req = new VeneerDefectSaveReqVO();
|
||||
req.setId(veneer.getId());
|
||||
req.setDefectData("");
|
||||
|
||||
assertDoesNotThrow(() -> veneerService.saveDefect(req));
|
||||
|
||||
VeneerDO db = veneerMapper.selectById(veneer.getId());
|
||||
|
||||
assertFalse(db.getDefect());
|
||||
assertNull(db.getDefectData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileExtension_whenEmpty() {
|
||||
assertEquals(".jpg", veneerService.getFileExtension("file."));
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
spring:
|
||||
main:
|
||||
lazy-initialization: true # 开启懒加载,加快速度
|
||||
banner-mode: off # 单元测试,禁用 Banner
|
||||
|
||||
--- #################### 数据库相关配置 ####################
|
||||
|
||||
spring:
|
||||
# 数据源配置项
|
||||
datasource:
|
||||
name: ruoyi-vue-pro
|
||||
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
|
||||
driver-class-name: org.h2.Driver
|
||||
username: sa
|
||||
password:
|
||||
druid:
|
||||
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
|
||||
initial-size: 1 # 单元测试,配置为 1,提升启动速度
|
||||
sql:
|
||||
init:
|
||||
schema-locations: classpath:/sql/create_tables.sql
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
port: 16379 # 端口(单元测试,使用 16379 端口)
|
||||
database: 0 # 数据库索引
|
||||
|
||||
mybatis:
|
||||
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
|
||||
|
||||
mybatis-plus:
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: AUTO # H2 主键递增
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
--- #################### 配置中心相关配置 ####################
|
||||
|
||||
--- #################### 服务保障相关配置 ####################
|
||||
|
||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
|
||||
|
||||
# Resilience4j 配置项
|
||||
|
||||
--- #################### 监控相关配置 ####################
|
||||
|
||||
--- #################### 晨丰相关配置 ####################
|
||||
|
||||
# 晨丰配置项,设置当前项目所有自定义的配置
|
||||
chenfeng:
|
||||
info:
|
||||
base-package: com.cf.imes.module
|
||||
captcha:
|
||||
timeout: 5m
|
||||
width: 160
|
||||
height: 60
|
||||
enable: true
|
||||
@@ -0,0 +1,4 @@
|
||||
<configuration>
|
||||
<!-- 引用 Spring Boot 的 logback 基础配置 -->
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||
</configuration>
|
||||
@@ -0,0 +1 @@
|
||||
DELETE FROM "veneers";
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
CREATE TABLE IF NOT EXISTS "veneers"
|
||||
(
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"veneer_no" varchar(32) NOT NULL,
|
||||
"source_veneer_no" varchar(32) DEFAULT NULL,
|
||||
"batch_no" varchar(32) DEFAULT NULL,
|
||||
"organ_id" bigint NOT NULL DEFAULT 1,
|
||||
"classification_name" varchar(64) NOT NULL,
|
||||
"veneer_name" varchar(64) NOT NULL,
|
||||
"product_level" tinyint NOT NULL,
|
||||
"brand" varchar(64) DEFAULT NULL,
|
||||
"spec" varchar(64) DEFAULT NULL,
|
||||
"material" varchar(64) DEFAULT NULL,
|
||||
"color" varchar(32) DEFAULT NULL,
|
||||
"factory" varchar(128) DEFAULT NULL,
|
||||
"num" int DEFAULT NULL,
|
||||
"defect" bit NOT NULL DEFAULT FALSE,
|
||||
"defect_data" clob DEFAULT NULL,
|
||||
"remain" bit NOT NULL DEFAULT FALSE,
|
||||
"source_plan_no" bigint DEFAULT NULL,
|
||||
"plan_no" bigint DEFAULT NULL,
|
||||
"status" tinyint NOT NULL DEFAULT 0,
|
||||
"width" decimal(8, 3) NOT NULL DEFAULT 0.000,
|
||||
"length" decimal(8, 3) NOT NULL DEFAULT 0.000,
|
||||
"thickness" decimal(8, 3) NOT NULL DEFAULT 0.000,
|
||||
"remark" varchar(255) DEFAULT NULL,
|
||||
"file_id" bigint DEFAULT NULL,
|
||||
"creator" varchar(64) DEFAULT NULL,
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT NULL,
|
||||
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '贴皮表 veneers_{N}';
|
||||
Reference in New Issue
Block a user