1、deptService单测完善;2、贴皮veneer service单测剥离真实db,使用纯mock;

This commit is contained in:
gaoqr
2026-01-22 11:37:22 +08:00
parent f22f3bb2ba
commit 7b919d7adb
4 changed files with 184 additions and 77 deletions
@@ -0,0 +1,55 @@
package com.cf.imes.module.executor.common;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.test.WithMockLoginUser;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.mockito.Mockito;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
*
*
* @author Gqr
* @since 2026/1/16 10:20
*/
public class WithMockLoginUserExtension implements BeforeEachCallback, AfterEachCallback {
@Override
public void afterEach(ExtensionContext context) {
SecurityContextHolder.clearContext();
}
@Override
public void beforeEach(ExtensionContext context) {
WithMockLoginUser ann = findAnnotation(context);
LoginUser loginUser = new LoginUser();
if (ann != null) {
loginUser.setId(ann.userId());
loginUser.setOrganId(ann.organId());
loginUser.setDeptId(ann.deptId());
loginUser.setNickname(ann.username());
loginUser.setIsSupAdmin(ann.isSuperAdmin());
} else {
return;
}
Authentication authentication = Mockito.mock(Authentication.class);
Mockito.when(authentication.getPrincipal()).thenReturn(loginUser);
SecurityContext securityContext = Mockito.mock(SecurityContext.class);
Mockito.when(securityContext.getAuthentication())
.thenReturn(authentication);
SecurityContextHolder.setContext(securityContext);
}
private WithMockLoginUser findAnnotation(ExtensionContext context) {
return context.getElement()
.map(el -> el.getAnnotation(WithMockLoginUser.class))
.orElse(null);
}
}
@@ -1,28 +1,37 @@
package com.cf.imes.module.executor.service.veneer;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
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.framework.test.core.ut.BaseMockitoUnitTest;
import com.cf.imes.module.executor.common.WithMockLoginUserExtension;
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.VeneerBatchMapper;
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.apache.ibatis.builder.MapperBuilderAssistant;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -32,15 +41,17 @@ import static com.cf.imes.module.executor.enums.ErrorCodeConstants.VENEER_NOT_EX
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.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -50,22 +61,37 @@ import static org.mockito.Mockito.when;
* @author Gqr
* @since 2026/1/7 15:08
*/
@Import(VeneerServiceImpl.class)
class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
@ExtendWith(WithMockLoginUserExtension.class)
class VeneerServiceImplTest extends BaseMockitoUnitTest {
@InjectMocks
private VeneerServiceImpl veneerService;
@MockitoBean
@Mock
private FileApi fileApi;
@MockitoBean
@Mock
private OrganApi organApi;
@Resource
@Mock
private VeneerMapper veneerMapper;
@Mock
private VeneerBatchMapper veneerBatchMapper;
@BeforeAll
static void init(){
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), VeneerDO.class);
}
@Test
void create_success_when_veneer_no_not_exists() {
// 模拟 Mapper 插入时生成 ID
doAnswer(invocation -> {
VeneerDO veneerDO = invocation.getArgument(0);
veneerDO.setId(100L); // 模拟自增主键
return null;
}).when(veneerMapper).insert(any(VeneerDO.class));
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
reqVO.setVeneerNo("VN-001");
reqVO.setClassificationName("测试分类");
@@ -74,10 +100,26 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
Long id = veneerService.create(reqVO);
assertNotNull(id);
VeneerDO db = veneerMapper.selectById(id);
assertEquals("VN-001", db.getVeneerNo());
// 断言
assertEquals(100L, id);
verify(veneerMapper).insert(argThat((VeneerDO veneerDO) ->
ObjectUtil.equals(veneerDO.getVeneerNo(), reqVO.getVeneerNo())
&& ObjectUtil.equals(veneerDO.getBatchNo(), reqVO.getBatchNo())
&& ObjectUtil.equals(veneerDO.getClassificationName(), reqVO.getClassificationName())
&& ObjectUtil.equals(veneerDO.getProductLevel(), reqVO.getProductLevel())
&& ObjectUtil.equals(veneerDO.getVeneerName(), reqVO.getVeneerName())
&& ObjectUtil.equals(veneerDO.getNum(), reqVO.getNum())
&& ObjectUtil.equals(veneerDO.getWidth(), reqVO.getWidth())
&& ObjectUtil.equals(veneerDO.getLength(), reqVO.getLength())
&& ObjectUtil.equals(veneerDO.getThickness(), reqVO.getThickness())
&& ObjectUtil.equals(veneerDO.getColor(), reqVO.getColor())
&& ObjectUtil.equals(veneerDO.getMaterial(), reqVO.getMaterial())
&& ObjectUtil.equals(veneerDO.getSpec(), reqVO.getSpec())
&& ObjectUtil.equals(veneerDO.getBrand(), reqVO.getBrand())
&& ObjectUtil.equals(veneerDO.getFactory(), reqVO.getFactory())
&& ObjectUtil.equals(veneerDO.getRemark(), reqVO.getRemark())
&& ObjectUtil.equals(veneerDO.getFileId(), reqVO.getFileId())
));
}
@Test
@@ -88,7 +130,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
exist.setClassificationName("分类");
exist.setVeneerName("贴皮");
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
veneerMapper.insert(exist);
when(veneerMapper.selectCount(any())).thenReturn(1L);
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
reqVO.setVeneerNo("VN-002");
@@ -100,11 +142,13 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Test
void update_success_when_same_veneer_no() {
VeneerDO exist = new VeneerDO();
exist.setId(100L);
exist.setVeneerNo("VN-100");
exist.setClassificationName("分类");
exist.setVeneerName("贴皮");
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
veneerMapper.insert(exist);
when(veneerMapper.selectById(anyLong())).thenReturn(exist);
when(veneerMapper.selectCount(any())).thenReturn(0L);
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
reqVO.setId(exist.getId());
@@ -114,26 +158,25 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
reqVO.setProductLevel(VeneerProductLevelEnum.B.getCode());
assertDoesNotThrow(() -> veneerService.update(reqVO));
// 校验是否更新
verify(veneerMapper, times(1)).updateById(any(VeneerDO.class));
}
@Test
void update_fail_when_veneer_no_exists() {
VeneerDO v1 = new VeneerDO();
v1.setId(100L);
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);
when(veneerMapper.selectById(anyLong())).thenReturn(v1);
when(veneerMapper.selectCount(any())).thenReturn(1L);
VeneerSaveReqVO reqVO = new VeneerSaveReqVO();
reqVO.setId(v2.getId());
reqVO.setId(v1.getId());
reqVO.setVeneerNo("VN-101"); // 冲突
assertServiceException(() -> veneerService.update(reqVO),
@@ -161,15 +204,18 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Test
void delete_success() {
VeneerDO exist = new VeneerDO();
exist.setId(100L);
exist.setVeneerNo("VN-200");
exist.setClassificationName("分类");
exist.setVeneerName("贴皮");
exist.setProductLevel(VeneerProductLevelEnum.A.getCode());
veneerMapper.insert(exist);
assertDoesNotThrow(() -> veneerService.delete(exist.getId()));
Long id = exist.getId();
when(veneerMapper.selectById(id)).thenReturn(exist);
assertNull(veneerMapper.selectById(exist.getId()));
assertDoesNotThrow(() -> veneerService.delete(id));
verify(veneerMapper, times(1)).deleteById(id);
}
@Test
@@ -247,7 +293,6 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
exist.setRemark("备注");
exist.setWidth(new BigDecimal(10));
exist.setThickness(new BigDecimal(9));
veneerMapper.insert(exist);
VeneerPageReqVO pageReqVO = new VeneerPageReqVO();
pageReqVO.setVeneerNo("VN-200");
@@ -258,6 +303,8 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
pageReqVO.setThickness(new BigDecimal[]{new BigDecimal(5)});
pageReqVO.setRemark("");
when(veneerMapper.selectPage(pageReqVO)).thenReturn(new PageResult<>(List.of(exist), 1L));
PageResult<VeneerRespVO> result =
veneerService.getPage(pageReqVO);
@@ -269,9 +316,12 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Test
void getPage_empty(){
VeneerPageReqVO reqVO = new VeneerPageReqVO();
when(veneerMapper.selectPage(reqVO)).thenReturn(new PageResult<>(null, 0L));
PageResult<VeneerRespVO> result = veneerService.getPage(reqVO);
assertNotNull(result);
assertEquals(0L, result.getList().size());
assertEquals(0L, result.getTotal());
}
@@ -281,6 +331,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
String zipped = JsonUtils.zipString(json);
VeneerDO veneer = new VeneerDO();
veneer.setId(100L);
veneer.setVeneerNo("VN-301");
veneer.setClassificationName("分类");
veneer.setVeneerName("贴皮");
@@ -288,7 +339,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
veneer.setDefectData(zipped);
veneer.setOrganId(1L);
veneerMapper.insert(veneer);
when(veneerMapper.selectById(veneer.getId())).thenReturn(veneer);
VeneerRespVO respVO = veneerService.get(veneer.getId());
@@ -306,7 +357,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
veneer.setProductLevel(1);
veneer.setOrganId(1L);
veneerMapper.insert(veneer);
when(veneerMapper.selectById(veneer.getId())).thenReturn(veneer);
VeneerRespVO respVO = veneerService.get(veneer.getId());
@@ -322,6 +373,8 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Test
void getOrgVeneerNo_empty() {
when(veneerMapper.selectList(any())).thenReturn(new ArrayList<>());
Map<String, Long> map = veneerService.getOrgVeneerNo();
assertNotNull(map);
assertTrue(map.isEmpty());
@@ -330,6 +383,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
@Test
void getOrgVeneerNo_success() {
VeneerDO v1 = new VeneerDO();
v1.setId(100L);
v1.setVeneerNo("VN-401");
v1.setClassificationName("分类");
v1.setVeneerName("贴皮");
@@ -337,14 +391,14 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
v1.setOrganId(1L);
VeneerDO v2 = new VeneerDO();
v2.setId(200L);
v2.setVeneerNo("VN-402");
v2.setClassificationName("分类");
v2.setVeneerName("贴皮");
v2.setProductLevel(VeneerProductLevelEnum.C.getCode());
v2.setOrganId(1L);
veneerMapper.insert(v1);
veneerMapper.insert(v2);
when(veneerMapper.selectList(any())).thenReturn(List.of(v1, v2));
Map<String, Long> map = veneerService.getOrgVeneerNo();
@@ -367,21 +421,12 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
veneerService.batchInsert(list);
// 验证数据真的进库了
List<VeneerDO> dbList = veneerMapper.selectList();
// 验证操作
verify(veneerBatchMapper, times(1)).insertBatchSomeColumn(list);
assertEquals(2, dbList.size());
veneerService.batchUpdate(list);
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());
verify(veneerBatchMapper, times(1)).updateBatch(list);
}
@Test
@@ -392,7 +437,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
o.setProductLevel(VeneerProductLevelEnum.A.getCode());
o.setDefectData(defectJson);
});
veneerMapper.insert(veneer);
when(veneerMapper.selectById(veneer.getId())).thenReturn(veneer);
VeneerDefectSaveReqVO req = new VeneerDefectSaveReqVO();
req.setId(veneer.getId());
@@ -400,12 +445,12 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
assertDoesNotThrow(() -> veneerService.saveDefect(req));
// 再查数据库
VeneerDO db = veneerMapper.selectById(veneer.getId());
assertTrue(db.getDefect());
assertNotNull(db.getDefectData());
assertEquals(defectJson, JsonUtils.unzipString(db.getDefectData()));
// 验证操作
verify(veneerMapper).update(argThat((LambdaUpdateWrapper wrapper) ->
wrapper.getSqlSegment().contains("id")
&& wrapper.getSqlSet().contains("defect")
&& wrapper.getSqlSet().contains("defect_data")
));
}
@Test
@@ -425,7 +470,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
o.setDefectData(null);
o.setDefect(false);
});
veneerMapper.insert(veneer);
when(veneerMapper.selectById(veneer.getId())).thenReturn(veneer);
VeneerDefectSaveReqVO req = new VeneerDefectSaveReqVO();
req.setId(veneer.getId());
@@ -433,10 +478,7 @@ class VeneerServiceImplTest extends BaseDbAndRedisUnitTest {
assertDoesNotThrow(() -> veneerService.saveDefect(req));
VeneerDO db = veneerMapper.selectById(veneer.getId());
assertFalse(db.getDefect());
assertNull(db.getDefectData());
verify(veneerMapper, never()).update(any());
}
@Test
@@ -299,20 +299,18 @@ public class DeptServiceImpl implements DeptService {
* @param deptDO
*/
private void validParentDept(DeptDO deptDO) {
if (ObjectUtil.isNotNull(deptDO) && ObjectUtil.isNotNull(deptDO.getParentId())) {
Long parentId = deptDO.getParentId();
DeptDO parentDept = deptMapper.selectById(parentId);
if (ObjectUtil.equal(parentId, 0L)) {
// 上级部门id是0代表是机构下最顶级的部门
return;
}
if (parentDept == null) {
throw new ServiceException(ErrorCodeConstants.DEPT_PARENT_NOT_EXITS);
} else if (!CommonStatusEnum.ENABLE.getStatus().equals(parentDept.getStatus())) {
throw new ServiceException(ErrorCodeConstants.DEPT_DISABLE, parentDept.getName());
} else {
validParentDept(parentDept);
}
Long parentId = deptDO.getParentId();
DeptDO parentDept = deptMapper.selectById(parentId);
if (ObjectUtil.equal(parentId, 0L)) {
// 上级部门id是0代表是机构下最顶级的部门
return;
}
if (parentDept == null) {
throw new ServiceException(ErrorCodeConstants.DEPT_PARENT_NOT_EXITS);
} else if (!CommonStatusEnum.ENABLE.getStatus().equals(parentDept.getStatus())) {
throw new ServiceException(ErrorCodeConstants.DEPT_DISABLE, parentDept.getName());
} else {
validParentDept(parentDept);
}
}
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.service.dept;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
@@ -625,12 +626,20 @@ class DeptServiceImplTest extends BaseMockitoUnitTest {
Set<Long> allInvalidDeptIds = deptService.getAllInvalidDeptIds(organId);
assertEquals(disableCount, allInvalidDeptIds.size());
OrganContextHolder.setOrganId(organId);
Set<Long> noOrganAllInvalidDeptIds = deptService.getAllInvalidDeptIds(null);
assertEquals(disableCount, noOrganAllInvalidDeptIds.size());
//
//
}
@Test
@WithMockLoginUser(organId = 100L)
void getAllInvalidDeptIds_outerOrganIdNull(){
OrganContextHolder.setOrganId(SecurityFrameworkUtils.getUserOrganId());
deptService.getAllInvalidDeptIds(null);
verify(deptMapper).selectList(any(LambdaQueryWrapper.class));
}
@Test
void testDeptNotExist_shouldReturn() {
// 不插入任何部门,确保 deptId 不存在
@@ -662,6 +671,7 @@ class DeptServiceImplTest extends BaseMockitoUnitTest {
DeptDO dept = new DeptDO();
dept.setName("测试部-启用");
dept.setStatus(CommonStatusEnum.ENABLE.getStatus());
dept.setParentId(DeptDO.PARENT_ID_ROOT);
Long id = dept.getId();
when(deptMapper.selectById(id)).thenReturn(dept);
@@ -700,6 +710,7 @@ class DeptServiceImplTest extends BaseMockitoUnitTest {
parent.setId(100L);
parent.setName("上级部门-启用");
parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
parent.setParentId(DeptDO.PARENT_ID_ROOT);
// 子部门启用
DeptDO child = new DeptDO();
@@ -749,6 +760,7 @@ class DeptServiceImplTest extends BaseMockitoUnitTest {
top.setId(100L);
top.setName("顶级部门-启用");
top.setStatus(CommonStatusEnum.ENABLE.getStatus());
top.setParentId(DeptDO.PARENT_ID_ROOT);
// 中间部门启用
DeptDO middle = new DeptDO();