优化 dept 部门的实现逻辑,以及相关的单元测试
This commit is contained in:
parent
bcf926f7c7
commit
6c9ef97122
|
@ -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";
|
||||
|
||||
/**
|
||||
* 拥有权限对应的菜单编号数组的缓存
|
||||
|
|
|
@ -39,31 +39,12 @@ public interface DeptService {
|
|||
void deleteDept(Long id);
|
||||
|
||||
/**
|
||||
* 筛选部门列表
|
||||
*
|
||||
* @param reqVO 筛选条件请求 VO
|
||||
* @return 部门列表
|
||||
*/
|
||||
List<DeptDO> getDeptList(DeptListReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获得指定部门的所有子部门
|
||||
* 获得部门信息
|
||||
*
|
||||
* @param id 部门编号
|
||||
* @return 子部门列表
|
||||
* @return 部门信息
|
||||
*/
|
||||
List<DeptDO> getChildDeptList(Long id);
|
||||
|
||||
/**
|
||||
* 获得所有子部门,从缓存中
|
||||
*
|
||||
* 注意,该缓存不是实时更新,最多会有 1 分钟延迟。
|
||||
* 一般来说,不会影响使用,因为部门的变更,不会频繁发生。
|
||||
*
|
||||
* @param id 父部门编号
|
||||
* @return 子部门列表
|
||||
*/
|
||||
Set<Long> getChildDeptIdListFromCache(Long id);
|
||||
DeptDO getDept(Long id);
|
||||
|
||||
/**
|
||||
* 获得部门信息数组
|
||||
|
@ -73,6 +54,14 @@ public interface DeptService {
|
|||
*/
|
||||
List<DeptDO> getDeptList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 筛选部门列表
|
||||
*
|
||||
* @param reqVO 筛选条件请求 VO
|
||||
* @return 部门列表
|
||||
*/
|
||||
List<DeptDO> getDeptList(DeptListReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获得指定编号的部门 Map
|
||||
*
|
||||
|
@ -88,12 +77,20 @@ public interface DeptService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 获得部门信息
|
||||
* 获得指定部门的所有子部门
|
||||
*
|
||||
* @param id 部门编号
|
||||
* @return 部门信息
|
||||
* @return 子部门列表
|
||||
*/
|
||||
DeptDO getDept(Long id);
|
||||
List<DeptDO> getChildDeptList(Long id);
|
||||
|
||||
/**
|
||||
* 获得所有子部门,从缓存中
|
||||
*
|
||||
* @param id 父部门编号
|
||||
* @return 子部门列表
|
||||
*/
|
||||
Set<Long> getChildDeptIdListFromCache(Long id);
|
||||
|
||||
/**
|
||||
* 校验部门们是否有效。如下情况,视为无效:
|
||||
|
|
|
@ -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<DeptDO> 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<DeptDO> getDeptList(Collection<Long> ids) {
|
||||
return deptMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeptDO> 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<Long> getChildDeptIdListFromCache(Long id) {
|
||||
// 补充说明:为什么该缓存会有 1 分钟的延迟?主要有两点:
|
||||
// 1. Spring Cache 无法方便的批量清理,所以使用 Redis 自动过期的方式。
|
||||
// 2. 变更父节点的时候,影响父子节点的数量很多,包括原父节点及其父节点,以及新父节点及其父节点。
|
||||
// 如果你真的对延迟比较敏感,可以考虑采用使用 allEntries = true 的方式,清理所有缓存。
|
||||
List<DeptDO> 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<DeptDO> 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<DeptDO> getDeptList(Collection<Long> ids) {
|
||||
return deptMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeptDO getDept(Long id) {
|
||||
return deptMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDeptList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
|
|
|
@ -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<Long, DeptDO> deptCache = deptService.getDeptCache();
|
||||
assertEquals(2, deptCache.size());
|
||||
assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId()));
|
||||
assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId()));
|
||||
// 断言 parentDeptCache 缓存
|
||||
Multimap<Long, DeptDO> 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<Long> ids = Arrays.asList(deptDO01.getId(), deptDO02.getId());
|
||||
|
||||
// 调用
|
||||
List<DeptDO> 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<DeptDO> 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<Long> ids = Arrays.asList(deptDO01.getId(), deptDO02.getId());
|
||||
|
||||
// 调用
|
||||
List<DeptDO> deptDOList = deptService.getDeptList(ids);
|
||||
Set<Long> 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<Long> 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<Long> 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<DeptDO>... consumers) {
|
||||
Consumer<DeptDO> consumer = (o) -> {
|
||||
o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
|
||||
};
|
||||
return randomPojo(DeptDO.class, ArrayUtils.append(consumer, consumers));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue