diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java index fa3b061d30..49559370d8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java @@ -57,10 +57,6 @@ public interface RedisKeyConstants { * 数据类型:String 子部门编号集合 */ String DEPT_CHILDREN_ID_LIST = "dept_children_ids"; - /** - * {@link #DEPT_CHILDREN_ID_LIST} 的过期时间 - */ - String DEPT_CHILDREN_ID_LIST_EXPIRE = "30s"; /** * 拥有权限对应的菜单编号数组的缓存 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java index f21b3e861a..1029b424c5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java @@ -39,31 +39,12 @@ public interface DeptService { void deleteDept(Long id); /** - * 筛选部门列表 - * - * @param reqVO 筛选条件请求 VO - * @return 部门列表 - */ - List getDeptList(DeptListReqVO reqVO); - - /** - * 获得指定部门的所有子部门 + * 获得部门信息 * * @param id 部门编号 - * @return 子部门列表 + * @return 部门信息 */ - List getChildDeptList(Long id); - - /** - * 获得所有子部门,从缓存中 - * - * 注意,该缓存不是实时更新,最多会有 1 分钟延迟。 - * 一般来说,不会影响使用,因为部门的变更,不会频繁发生。 - * - * @param id 父部门编号 - * @return 子部门列表 - */ - Set getChildDeptIdListFromCache(Long id); + DeptDO getDept(Long id); /** * 获得部门信息数组 @@ -73,6 +54,14 @@ public interface DeptService { */ List getDeptList(Collection ids); + /** + * 筛选部门列表 + * + * @param reqVO 筛选条件请求 VO + * @return 部门列表 + */ + List getDeptList(DeptListReqVO reqVO); + /** * 获得指定编号的部门 Map * @@ -88,12 +77,20 @@ public interface DeptService { } /** - * 获得部门信息 + * 获得指定部门的所有子部门 * * @param id 部门编号 - * @return 部门信息 + * @return 子部门列表 */ - DeptDO getDept(Long id); + List getChildDeptList(Long id); + + /** + * 获得所有子部门,从缓存中 + * + * @param id 父部门编号 + * @return 子部门列表 + */ + Set getChildDeptIdListFromCache(Long id); /** * 校验部门们是否有效。如下情况,视为无效: diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index 5f0fbeb5f2..b68453cded 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; @@ -11,7 +12,9 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; +import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -37,6 +40,8 @@ public class DeptServiceImpl implements DeptService { private DeptMapper deptMapper; @Override + @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, + allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 public Long createDept(DeptCreateReqVO reqVO) { // 校验正确性 if (reqVO.getParentId() == null) { @@ -50,6 +55,8 @@ public class DeptServiceImpl implements DeptService { } @Override + @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, + allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 public void updateDept(DeptUpdateReqVO reqVO) { // 校验正确性 if (reqVO.getParentId() == null) { @@ -62,6 +69,8 @@ public class DeptServiceImpl implements DeptService { } @Override + @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, + allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 public void deleteDept(Long id) { // 校验是否存在 validateDeptExists(id); @@ -73,6 +82,72 @@ public class DeptServiceImpl implements DeptService { deptMapper.deleteById(id); } + private void validateForCreateOrUpdate(Long id, Long parentId, String name) { + // 校验自己存在 + validateDeptExists(id); + // 校验父部门的有效性 + validateParentDept(id, parentId); + // 校验部门名的唯一性 + validateDeptNameUnique(id, parentId, name); + } + + @VisibleForTesting + void validateDeptExists(Long id) { + if (id == null) { + return; + } + DeptDO dept = deptMapper.selectById(id); + if (dept == null) { + throw exception(DEPT_NOT_FOUND); + } + } + + @VisibleForTesting + void validateParentDept(Long id, Long parentId) { + if (parentId == null || DeptIdEnum.ROOT.getId().equals(parentId)) { + return; + } + // 不能设置自己为父部门 + if (parentId.equals(id)) { + throw exception(DEPT_PARENT_ERROR); + } + // 父岗位不存在 + DeptDO dept = deptMapper.selectById(parentId); + if (dept == null) { + throw exception(DEPT_PARENT_NOT_EXITS); + } + // 父部门不能是原来的子部门 + List children = getChildDeptList(id); + if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) { + throw exception(DEPT_PARENT_IS_CHILD); + } + } + + @VisibleForTesting + void validateDeptNameUnique(Long id, Long parentId, String name) { + DeptDO dept = deptMapper.selectByParentIdAndName(parentId, name); + if (dept == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的岗位 + if (id == null) { + throw exception(DEPT_NAME_DUPLICATE); + } + if (ObjectUtil.notEqual(dept.getId(), id)) { + throw exception(DEPT_NAME_DUPLICATE); + } + } + + @Override + public DeptDO getDept(Long id) { + return deptMapper.selectById(id); + } + + @Override + public List getDeptList(Collection ids) { + return deptMapper.selectBatchIds(ids); + } + @Override public List getDeptList(DeptListReqVO reqVO) { return deptMapper.selectList(reqVO); @@ -99,84 +174,12 @@ public class DeptServiceImpl implements DeptService { @Override @DataPermission(enable = false) // 禁用数据权限,避免简历不正确的缓存 - @Cacheable(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST - + "#" + RedisKeyConstants.DEPT_CHILDREN_ID_LIST_EXPIRE, key = "#id") + @Cacheable(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, key = "#id") public Set getChildDeptIdListFromCache(Long id) { - // 补充说明:为什么该缓存会有 1 分钟的延迟?主要有两点: - // 1. Spring Cache 无法方便的批量清理,所以使用 Redis 自动过期的方式。 - // 2. 变更父节点的时候,影响父子节点的数量很多,包括原父节点及其父节点,以及新父节点及其父节点。 - // 如果你真的对延迟比较敏感,可以考虑采用使用 allEntries = true 的方式,清理所有缓存。 List children = getChildDeptList(id); return convertSet(children, DeptDO::getId); } - private void validateForCreateOrUpdate(Long id, Long parentId, String name) { - // 校验自己存在 - validateDeptExists(id); - // 校验父部门的有效性 - validateParentDeptEnable(id, parentId); - // 校验部门名的唯一性 - validateDeptNameUnique(id, parentId, name); - } - - private void validateParentDeptEnable(Long id, Long parentId) { - if (parentId == null || DeptIdEnum.ROOT.getId().equals(parentId)) { - return; - } - // 不能设置自己为父部门 - if (parentId.equals(id)) { - throw exception(DEPT_PARENT_ERROR); - } - // 父岗位不存在 - DeptDO dept = deptMapper.selectById(parentId); - if (dept == null) { - throw exception(DEPT_PARENT_NOT_EXITS); - } - // 父部门被禁用 - if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getStatus())) { - throw exception(DEPT_NOT_ENABLE); - } - // 父部门不能是原来的子部门 - List children = getChildDeptList(id); - if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) { - throw exception(DEPT_PARENT_IS_CHILD); - } - } - - private void validateDeptExists(Long id) { - if (id == null) { - return; - } - DeptDO dept = deptMapper.selectById(id); - if (dept == null) { - throw exception(DEPT_NOT_FOUND); - } - } - - private void validateDeptNameUnique(Long id, Long parentId, String name) { - DeptDO menu = deptMapper.selectByParentIdAndName(parentId, name); - if (menu == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的岗位 - if (id == null) { - throw exception(DEPT_NAME_DUPLICATE); - } - if (!menu.getId().equals(id)) { - throw exception(DEPT_NAME_DUPLICATE); - } - } - - @Override - public List getDeptList(Collection ids) { - return deptMapper.selectBatchIds(ids); - } - - @Override - public DeptDO getDept(Long id) { - return deptMapper.selectById(id); - } - @Override public void validateDeptList(Collection ids) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java index 08ee3d346c..cf9dc5a35d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.system.service.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; @@ -11,26 +9,20 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateRe import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; -import com.google.common.collect.Multimap; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; +import java.util.Set; -import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.verify; /** * {@link DeptServiceImpl} 的单元测试类 @@ -44,39 +36,163 @@ public class DeptServiceImplTest extends BaseDbUnitTest { private DeptServiceImpl deptService; @Resource private DeptMapper deptMapper; - @MockBean - private DeptProducer deptProducer; - - @BeforeEach - public void setUp() { - // 清理租户上下文 - TenantContextHolder.clear(); - } @Test - public void testInitLocalCache() { - // mock 数据 - DeptDO deptDO1 = randomDeptDO(); - deptMapper.insert(deptDO1); - DeptDO deptDO2 = randomDeptDO(); - deptMapper.insert(deptDO2); + public void testCreateDept() { + // 准备参数 + DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { + o.setParentId(DeptIdEnum.ROOT.getId()); + o.setStatus(randomCommonStatus()); + }); // 调用 - deptService.initLocalCache(); - // 断言 deptCache 缓存 - Map deptCache = deptService.getDeptCache(); - assertEquals(2, deptCache.size()); - assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId())); - assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId())); - // 断言 parentDeptCache 缓存 - Multimap parentDeptCache = deptService.getParentDeptCache(); - assertEquals(2, parentDeptCache.size()); - assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId())); - assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId())); + Long deptId = deptService.createDept(reqVO); + // 断言 + assertNotNull(deptId); + // 校验记录的属性是否正确 + DeptDO deptDO = deptMapper.selectById(deptId); + assertPojoEquals(reqVO, deptDO); } @Test - public void testListDepts() { + public void testUpdateDept() { + // mock 数据 + DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); + deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 + // 准备参数 + DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { + // 设置更新的 ID + o.setParentId(DeptIdEnum.ROOT.getId()); + o.setId(dbDeptDO.getId()); + o.setStatus(randomCommonStatus()); + }); + + // 调用 + deptService.updateDept(reqVO); + // 校验是否更新正确 + DeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, deptDO); + } + + @Test + public void testDeleteDept_success() { + // mock 数据 + DeptDO dbDeptDO = randomPojo(DeptDO.class); + deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbDeptDO.getId(); + + // 调用 + deptService.deleteDept(id); + // 校验数据不存在了 + assertNull(deptMapper.selectById(id)); + } + + @Test + public void testDeleteDept_exitsChildren() { + // mock 数据 + DeptDO parentDept = randomPojo(DeptDO.class); + deptMapper.insert(parentDept);// @Sql: 先插入出一条存在的数据 + // 准备参数 + DeptDO childrenDeptDO = randomPojo(DeptDO.class, o -> { + o.setParentId(parentDept.getId()); + o.setStatus(randomCommonStatus()); + }); + // 插入子部门 + deptMapper.insert(childrenDeptDO); + + // 调用, 并断言异常 + assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN); + } + + @Test + public void testValidateDeptExists_notFound() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> deptService.validateDeptExists(id), DEPT_NOT_FOUND); + } + + @Test + public void testValidateParentDept_parentError() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> deptService.validateParentDept(id, id), + DEPT_PARENT_ERROR); + } + + @Test + public void testValidateParentDept_parentIsChild() { + // mock 数据(父节点) + DeptDO parentDept = randomPojo(DeptDO.class); + deptMapper.insert(parentDept); + // mock 数据(子节点) + DeptDO childDept = randomPojo(DeptDO.class, o -> { + o.setParentId(parentDept.getId()); + }); + deptMapper.insert(childDept); + + // 准备参数 + Long id = parentDept.getId(); + Long parentId = childDept.getId(); + + // 调用, 并断言异常 + assertServiceException(() -> deptService.validateParentDept(id, parentId), DEPT_PARENT_IS_CHILD); + } + + @Test + public void testValidateNameUnique_duplicate() { + // mock 数据 + DeptDO deptDO = randomPojo(DeptDO.class); + deptMapper.insert(deptDO); + + // 准备参数 + Long id = randomLongId(); + Long parentId = deptDO.getParentId(); + String name = deptDO.getName(); + + // 调用, 并断言异常 + assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name), + DEPT_NAME_DUPLICATE); + } + + @Test + public void testGetDept() { + // mock 数据 + DeptDO deptDO = randomPojo(DeptDO.class); + deptMapper.insert(deptDO); + // 准备参数 + Long id = deptDO.getId(); + + // 调用 + DeptDO dbDept = deptService.getDept(id); + // 断言 + assertEquals(deptDO, dbDept); + } + + @Test + public void testGetDeptList_ids() { + // mock 数据 + DeptDO deptDO01 = randomPojo(DeptDO.class); + deptMapper.insert(deptDO01); + DeptDO deptDO02 = randomPojo(DeptDO.class); + deptMapper.insert(deptDO02); + // 准备参数 + List ids = Arrays.asList(deptDO01.getId(), deptDO02.getId()); + + // 调用 + List deptDOList = deptService.getDeptList(ids); + // 断言 + assertEquals(2, deptDOList.size()); + assertEquals(deptDO01, deptDOList.get(0)); + assertEquals(deptDO02, deptDOList.get(1)); + } + + @Test + public void testGetDeptList_reqVO() { // mock 数据 DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到 o.setName("开发部"); @@ -100,216 +216,55 @@ public class DeptServiceImplTest extends BaseDbUnitTest { } @Test - public void testCreateDept_success() { + public void testGetChildDeptList() { + // mock 数据(1 级别子节点) + DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1")); + deptMapper.insert(dept1); + DeptDO dept2 = randomPojo(DeptDO.class, o -> o.setName("2")); + deptMapper.insert(dept2); + // mock 数据(2 级子节点) + DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId())); + deptMapper.insert(dept1a); + DeptDO dept2a = randomPojo(DeptDO.class, o -> o.setName("2-a").setParentId(dept2.getId())); + deptMapper.insert(dept2a); // 准备参数 - DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { - o.setParentId(DeptIdEnum.ROOT.getId()); - o.setStatus(randomCommonStatus()); - }); + Long id = dept1.getParentId(); // 调用 - Long deptId = deptService.createDept(reqVO); + List result = deptService.getChildDeptList(id); // 断言 - assertNotNull(deptId); - // 校验记录的属性是否正确 - DeptDO deptDO = deptMapper.selectById(deptId); - assertPojoEquals(reqVO, deptDO); - // 校验调用 - verify(deptProducer).sendDeptRefreshMessage(); + assertEquals(result.size(), 2); + assertPojoEquals(dept1, result.get(0)); + assertPojoEquals(dept1a, result.get(1)); } @Test - public void testUpdateDept_success() { - // mock 数据 - DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); - deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 + public void testGetChildDeptListFromCache() { + // mock 数据(1 级别子节点) + DeptDO dept1 = randomPojo(DeptDO.class, o -> o.setName("1")); + deptMapper.insert(dept1); + DeptDO dept2 = randomPojo(DeptDO.class, o -> o.setName("2")); + deptMapper.insert(dept2); + // mock 数据(2 级子节点) + DeptDO dept1a = randomPojo(DeptDO.class, o -> o.setName("1-a").setParentId(dept1.getId())); + deptMapper.insert(dept1a); + DeptDO dept2a = randomPojo(DeptDO.class, o -> o.setName("2-a").setParentId(dept2.getId())); + deptMapper.insert(dept2a); // 准备参数 - DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { - // 设置更新的 ID - o.setParentId(DeptIdEnum.ROOT.getId()); - o.setId(dbDeptDO.getId()); - o.setStatus(randomCommonStatus()); - }); + Long id = dept1.getParentId(); // 调用 - deptService.updateDept(reqVO); - // 校验是否更新正确 - DeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, deptDO); - // 校验调用 - verify(deptProducer).sendDeptRefreshMessage(); - } - - @Test - public void testDeleteDept_success() { - // mock 数据 - DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); - deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbDeptDO.getId(); - - // 调用 - deptService.deleteDept(id); - // 校验数据不存在了 - assertNull(deptMapper.selectById(id)); - // 校验调用 - verify(deptProducer).sendDeptRefreshMessage(); - } - - @Test - public void testValidateDept_nameDuplicateForUpdate() { - // mock 数据 - DeptDO deptDO = randomDeptDO(); - // 设置根节点部门 - deptDO.setParentId(DeptIdEnum.ROOT.getId()); - deptMapper.insert(deptDO); - // mock 数据 稍后模拟重复它的 name - DeptDO nameDeptDO = randomDeptDO(); - // 设置根节点部门 - nameDeptDO.setParentId(DeptIdEnum.ROOT.getId()); - deptMapper.insert(nameDeptDO); - // 准备参数 - DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { - // 设置根节点部门 - o.setParentId(DeptIdEnum.ROOT.getId()); - // 设置更新的 ID - o.setId(deptDO.getId()); - // 模拟 name 重复 - o.setName(nameDeptDO.getName()); - }); - - // 调用, 并断言异常 - assertServiceException(() -> deptService.updateDept(reqVO), DEPT_NAME_DUPLICATE); - } - - @Test - public void testValidateDept_parentNotExitsForCreate() { - // 准备参数 - DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, - o -> o.setStatus(randomCommonStatus())); - - // 调用,并断言异常 - assertServiceException(() -> deptService.createDept(reqVO), DEPT_PARENT_NOT_EXITS); - } - - @Test - public void testValidateDept_notFoundForDelete() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> deptService.deleteDept(id), DEPT_NOT_FOUND); - } - - @Test - public void testValidateDept_exitsChildrenForDelete() { - // mock 数据 - DeptDO parentDept = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); - deptMapper.insert(parentDept);// @Sql: 先插入出一条存在的数据 - // 准备参数 - DeptDO childrenDeptDO = randomPojo(DeptDO.class, o -> { - o.setParentId(parentDept.getId()); - o.setStatus(randomCommonStatus()); - }); - // 插入子部门 - deptMapper.insert(childrenDeptDO); - // 调用, 并断言异常 - assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN); - } - - @Test - public void testValidateDept_parentErrorForUpdate() { - // mock 数据 - DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); - deptMapper.insert(dbDeptDO); - // 准备参数 - DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { - // 设置自己为父部门 - o.setParentId(dbDeptDO.getId()); - // 设置更新的 ID - o.setId(dbDeptDO.getId()); - }); - - // 调用, 并断言异常 - assertServiceException(() -> deptService.updateDept(reqVO), DEPT_PARENT_ERROR); - } - - @Test - public void testValidateDept_notEnableForCreate() { - // mock 数据 - DeptDO deptDO = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())); - deptMapper.insert(deptDO); - // 准备参数 - DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { - // 设置未启用的部门为父部门 - o.setParentId(deptDO.getId()); - }); - - // 调用, 并断言异常 - assertServiceException(() -> deptService.createDept(reqVO), DEPT_NOT_ENABLE); - } - - @Test - public void testCheckDept_parentIsChildForUpdate() { - // mock 数据 - DeptDO parentDept = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - deptMapper.insert(parentDept); - DeptDO childDept = randomPojo(DeptDO.class, o -> { - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setParentId(parentDept.getId()); - }); - deptMapper.insert(childDept); - // 初始化本地缓存 - deptService.initLocalCache(); - - // 准备参数 - DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { - // 设置自己的子部门为父部门 - o.setParentId(childDept.getId()); - // 设置更新的 ID - o.setId(parentDept.getId()); - }); - - // 调用, 并断言异常 - assertServiceException(() -> deptService.updateDept(reqVO), DEPT_PARENT_IS_CHILD); - } - - @Test - public void testGetDeptList() { - // mock 数据 - DeptDO deptDO01 = randomDeptDO(); - deptMapper.insert(deptDO01); - DeptDO deptDO02 = randomDeptDO(); - deptMapper.insert(deptDO02); - // 准备参数 - List ids = Arrays.asList(deptDO01.getId(), deptDO02.getId()); - - // 调用 - List deptDOList = deptService.getDeptList(ids); + Set result = deptService.getChildDeptIdListFromCache(id); // 断言 - assertEquals(2, deptDOList.size()); - assertEquals(deptDO01, deptDOList.get(0)); - assertEquals(deptDO02, deptDOList.get(1)); - } - - @Test - public void testGetDept() { - // mock 数据 - DeptDO deptDO = randomDeptDO(); - deptMapper.insert(deptDO); - // 准备参数 - Long id = deptDO.getId(); - - // 调用 - DeptDO dbDept = deptService.getDept(id); - // 断言 - assertEquals(deptDO, dbDept); + assertEquals(result.size(), 2); + assertTrue(result.contains(dept1.getId())); + assertTrue(result.contains(dept1a.getId())); } @Test public void testValidateDeptList_success() { // mock 数据 - DeptDO deptDO = randomDeptDO().setStatus(CommonStatusEnum.ENABLE.getStatus()); + DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.ENABLE.getStatus()); deptMapper.insert(deptDO); // 准备参数 List ids = singletonList(deptDO.getId()); @@ -330,7 +285,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { @Test public void testValidateDeptList_notEnable() { // mock 数据 - DeptDO deptDO = randomDeptDO().setStatus(CommonStatusEnum.DISABLE.getStatus()); + DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.DISABLE.getStatus()); deptMapper.insert(deptDO); // 准备参数 List ids = singletonList(deptDO.getId()); @@ -339,12 +294,4 @@ public class DeptServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> deptService.validateDeptList(ids), DEPT_NOT_ENABLE, deptDO.getName()); } - @SafeVarargs - private static DeptDO randomDeptDO(Consumer... consumers) { - Consumer consumer = (o) -> { - o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 - }; - return randomPojo(DeptDO.class, ArrayUtils.append(consumer, consumers)); - } - }