Explorar el Código

完善 PermissionService 的单元测试

YunaiV hace 2 años
padre
commit
5572bf3fcb

+ 2 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java

@@ -37,9 +37,9 @@ public class PermissionController {
 
     @Operation(summary = "获得角色拥有的菜单编号")
     @Parameter(name = "roleId", description = "角色编号", required = true)
-    @GetMapping("/list-role-resources")
+    @GetMapping("/list-role-menus")
     @PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
-    public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
+    public CommonResult<Set<Long>> getRoleMenuList(Long roleId) {
         return success(permissionService.getRoleMenuListByRoleId(roleId));
     }
 

+ 8 - 8
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java

@@ -26,6 +26,14 @@ public interface RedisKeyConstants {
             "social_auth_state:%s", // 参数为 state
             STRING, String.class, Duration.ofHours(24)); // 值为 state
 
+    /**
+     * 指定部门的所有子部门编号数组的缓存
+     *
+     * KEY 格式:dept_children_ids::{id}
+     * 数据类型:String 子部门编号集合
+     */
+    String DEPT_CHILDREN_ID_LIST = "dept_children_ids";
+
     /**
      * 角色的缓存
      *
@@ -50,14 +58,6 @@ public interface RedisKeyConstants {
      */
     String MENU_ROLE_ID_LIST = "menu_role_ids";
 
-    /**
-     * 指定部门的所有子部门编号数组的缓存
-     *
-     * KEY 格式:dept_children_ids::{id}
-     * 数据类型:String 子部门编号集合
-     */
-    String DEPT_CHILDREN_ID_LIST = "dept_children_ids";
-
     /**
      * 拥有权限对应的菜单编号数组的缓存
      *

+ 24 - 24
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java

@@ -33,6 +33,16 @@ public interface PermissionService {
      */
     boolean hasAnyRoles(Long userId, String... roles);
 
+    // ========== 角色-菜单的相关方法  ==========
+
+    /**
+     * 设置角色菜单
+     *
+     * @param roleId 角色编号
+     * @param menuIds 菜单编号集合
+     */
+    void assignRoleMenu(Long roleId, Set<Long> menuIds);
+
     /**
      * 处理角色删除时,删除关联授权数据
      *
@@ -47,15 +57,6 @@ public interface PermissionService {
      */
     void processMenuDeleted(Long menuId);
 
-    /**
-     * 处理用户删除是,删除关联授权数据
-     *
-     * @param userId 用户编号
-     */
-    void processUserDeleted(Long userId);
-
-    // ========== 角色-菜单的相关方法  ==========
-
     /**
      * 获得角色拥有的菜单编号集合
      *
@@ -85,20 +86,27 @@ public interface PermissionService {
     // ========== 用户-角色的相关方法  ==========
 
     /**
-     * 获得拥有多个角色的用户编号集合
+     * 设置用户角色
      *
+     * @param userId 角色编号
      * @param roleIds 角色编号集合
-     * @return 用户编号集合
      */
-    Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds);
+    void assignUserRole(Long userId, Set<Long> roleIds);
 
     /**
-     * 设置角色菜单
+     * 处理用户删除时,删除关联授权数据
      *
-     * @param roleId 角色编号
-     * @param menuIds 菜单编号集合
+     * @param userId 用户编号
      */
-    void assignRoleMenu(Long roleId, Set<Long> menuIds);
+    void processUserDeleted(Long userId);
+
+    /**
+     * 获得拥有多个角色的用户编号集合
+     *
+     * @param roleIds 角色编号集合
+     * @return 用户编号集合
+     */
+    Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds);
 
     /**
      * 获得用户拥有的角色编号集合
@@ -116,14 +124,6 @@ public interface PermissionService {
      */
     Set<Long> getUserRoleIdListByUserIdFromCache(Long userId);
 
-    /**
-     * 设置用户角色
-     *
-     * @param userId 角色编号
-     * @param roleIds 角色编号集合
-     */
-    void assignUserRole(Long userId, Set<Long> roleIds);
-
     // ========== 用户-部门的相关方法  ==========
 
     /**

+ 79 - 56
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java

@@ -18,18 +18,19 @@ import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.Sets;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.function.Supplier;
 
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@@ -99,7 +100,7 @@ public class PermissionServiceImpl implements PermissionService {
         // 判断是否有权限
         Set<Long> roleIds = convertSet(roles, RoleDO::getId);
         for (Long menuId : menuIds) {
-            // 拥有该角色的菜单编号数组
+            // 获得拥有该菜单的角色编号集合
             Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menuId);
             // 如果有交集,说明有权限
             if (CollUtil.containsAny(menuRoleIds, roleIds)) {
@@ -127,24 +128,12 @@ public class PermissionServiceImpl implements PermissionService {
         return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
     }
 
-    @Override
-    public Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds) {
-        // 如果是管理员的情况下,获取全部菜单编号
-        if (roleService.hasAnySuperAdmin(roleIds)) {
-            return convertSet(menuService.getMenuList(), MenuDO::getId);
-        }
-        // 如果是非管理员的情况下,获得拥有的菜单编号
-        return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId);
-    }
+    // ========== 角色-菜单的相关方法  ==========
 
     @Override
-    @Cacheable(value = RedisKeyConstants.MENU_ROLE_ID_LIST, key = "#menuId")
-    public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) {
-        return convertSet(roleMenuMapper.selectListByMenuId(menuId), RoleMenuDO::getRoleId);
-    }
-
-    @Override
-//    @Transactional(rollbackFor = Exception.class) // TODO 芋艿:不能使用 MySQL 事务
+    @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
+    @CacheEvict(value = RedisKeyConstants.MENU_ROLE_ID_LIST,
+            allEntries = true) // allEntries 清空所有缓存,主要一次更新涉及到的 menuIds 较多,反倒批量会更快
     public void assignRoleMenu(Long roleId, Set<Long> menuIds) {
         // 获得角色拥有菜单编号
         Set<Long> dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), RoleMenuDO::getMenuId);
@@ -152,7 +141,7 @@ public class PermissionServiceImpl implements PermissionService {
         Collection<Long> createMenuIds = CollUtil.subtract(menuIds, dbMenuIds);
         Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds);
         // 执行新增和删除。对于已经授权的菜单,不用做任何处理
-        if (!CollectionUtil.isEmpty(createMenuIds)) {
+        if (CollUtil.isNotEmpty(createMenuIds)) {
             roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> {
                 RoleMenuDO entity = new RoleMenuDO();
                 entity.setRoleId(roleId);
@@ -160,44 +149,57 @@ public class PermissionServiceImpl implements PermissionService {
                 return entity;
             }));
         }
-        if (!CollectionUtil.isEmpty(deleteMenuIds)) {
+        if (CollUtil.isNotEmpty(deleteMenuIds)) {
             roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds);
         }
     }
 
     @Override
-    public Set<Long> getUserRoleIdListByUserId(Long userId) {
-        return convertSet(userRoleMapper.selectListByUserId(userId), UserRoleDO::getRoleId);
+    @Transactional(rollbackFor = Exception.class)
+    @Caching(evict = {
+            @CacheEvict(value = RedisKeyConstants.MENU_ROLE_ID_LIST,
+                    allEntries = true), // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 menu 缓存们
+            @CacheEvict(value = RedisKeyConstants.USER_ROLE_ID_LIST,
+                    allEntries = true) // allEntries 清空所有缓存,此处无法方便获得 roleId 对应的 user 缓存们
+    })
+    public void processRoleDeleted(Long roleId) {
+        // 标记删除 UserRole
+        userRoleMapper.deleteListByRoleId(roleId);
+        // 标记删除 RoleMenu
+        roleMenuMapper.deleteListByRoleId(roleId);
     }
 
     @Override
-    @Cacheable(value = RedisKeyConstants.USER_ROLE_ID_LIST, key = "#userId")
-    public Set<Long> getUserRoleIdListByUserIdFromCache(Long userId) {
-        return getUserRoleIdListByUserId(userId);
+    @CacheEvict(value = RedisKeyConstants.MENU_ROLE_ID_LIST, key = "#menuId")
+    public void processMenuDeleted(Long menuId) {
+        roleMenuMapper.deleteListByMenuId(menuId);
     }
 
     @Override
-    public Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds) {
-        return convertSet(userRoleMapper.selectListByRoleIds(roleIds), UserRoleDO::getUserId);
+    public Set<Long> getRoleMenuListByRoleId(Collection<Long> roleIds) {
+        if (CollUtil.isEmpty(roleIds)) {
+            return Collections.emptySet();
+        }
+
+        // 如果是管理员的情况下,获取全部菜单编号
+        if (roleService.hasAnySuperAdmin(roleIds)) {
+            return convertSet(menuService.getMenuList(), MenuDO::getId);
+        }
+        // 如果是非管理员的情况下,获得拥有的菜单编号
+        return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId);
     }
 
-    /**
-     * 获得用户拥有的角色,并且这些角色是开启状态的
-     *
-     * @param userId 用户编号
-     * @return 用户拥有的角色
-     */
-    private List<RoleDO> getEnableUserRoleListByUserIdFromCache(Long userId) {
-        // 获得用户拥有的角色编号
-        Set<Long> roleIds = getSelf().getUserRoleIdListByUserIdFromCache(userId);
-        // 获得角色数组,并移除被禁用的
-        List<RoleDO> roles = roleService.getRoleListFromCache(roleIds);
-        roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus()));
-        return roles;
+    @Override
+    @Cacheable(value = RedisKeyConstants.MENU_ROLE_ID_LIST, key = "#menuId")
+    public Set<Long> getMenuRoleIdListByMenuIdFromCache(Long menuId) {
+        return convertSet(roleMenuMapper.selectListByMenuId(menuId), RoleMenuDO::getRoleId);
     }
 
+    // ========== 用户-角色的相关方法  ==========
+
     @Override
-    //    @Transactional(rollbackFor = Exception.class) // TODO 芋艿:不能使用 MySQL 事务
+    @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
+    @CacheEvict(value = RedisKeyConstants.USER_ROLE_ID_LIST, key = "#userId")
     public void assignUserRole(Long userId, Set<Long> roleIds) {
         // 获得角色拥有角色编号
         Set<Long> dbRoleIds = convertSet(userRoleMapper.selectListByUserId(userId),
@@ -220,27 +222,48 @@ public class PermissionServiceImpl implements PermissionService {
     }
 
     @Override
-    public void assignRoleDataScope(Long roleId, Integer dataScope, Set<Long> dataScopeDeptIds) {
-        roleService.updateRoleDataScope(roleId, dataScope, dataScopeDeptIds);
+    @CacheEvict(value = RedisKeyConstants.USER_ROLE_ID_LIST, key = "#userId")
+    public void processUserDeleted(Long userId) {
+        userRoleMapper.deleteListByUserId(userId);
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void processRoleDeleted(Long roleId) {
-        // 标记删除 UserRole
-        userRoleMapper.deleteListByRoleId(roleId);
-        // 标记删除 RoleMenu
-        roleMenuMapper.deleteListByRoleId(roleId);
+    public Set<Long> getUserRoleIdListByUserId(Long userId) {
+        return convertSet(userRoleMapper.selectListByUserId(userId), UserRoleDO::getRoleId);
     }
 
     @Override
-    public void processMenuDeleted(Long menuId) {
-        roleMenuMapper.deleteListByMenuId(menuId);
+    @Cacheable(value = RedisKeyConstants.USER_ROLE_ID_LIST, key = "#userId")
+    public Set<Long> getUserRoleIdListByUserIdFromCache(Long userId) {
+        return getUserRoleIdListByUserId(userId);
     }
 
     @Override
-    public void processUserDeleted(Long userId) {
-        userRoleMapper.deleteListByUserId(userId);
+    public Set<Long> getUserRoleIdListByRoleId(Collection<Long> roleIds) {
+        return convertSet(userRoleMapper.selectListByRoleIds(roleIds), UserRoleDO::getUserId);
+    }
+
+    /**
+     * 获得用户拥有的角色,并且这些角色是开启状态的
+     *
+     * @param userId 用户编号
+     * @return 用户拥有的角色
+     */
+    @VisibleForTesting
+    List<RoleDO> getEnableUserRoleListByUserIdFromCache(Long userId) {
+        // 获得用户拥有的角色编号
+        Set<Long> roleIds = getSelf().getUserRoleIdListByUserIdFromCache(userId);
+        // 获得角色数组,并移除被禁用的
+        List<RoleDO> roles = roleService.getRoleListFromCache(roleIds);
+        roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus()));
+        return roles;
+    }
+
+    // ========== 用户-部门的相关方法  ==========
+
+    @Override
+    public void assignRoleDataScope(Long roleId, Integer dataScope, Set<Long> dataScopeDeptIds) {
+        roleService.updateRoleDataScope(roleId, dataScope, dataScopeDeptIds);
     }
 
     @Override

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java

@@ -189,6 +189,9 @@ public class RoleServiceImpl implements RoleService {
 
     @Override
     public List<RoleDO> getRoleList(Collection<Long> ids) {
+        if (CollectionUtil.isEmpty(ids)) {
+            return Collections.emptyList();
+        }
         return roleMapper.selectBatchIds(ids);
     }
 

+ 257 - 177
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.system.service.permission;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
@@ -25,7 +24,6 @@ import org.springframework.context.annotation.Import;
 import javax.annotation.Resource;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import static cn.hutool.core.collection.ListUtil.toList;
@@ -126,24 +124,73 @@ public class PermissionServiceTest extends BaseDbUnitTest {
         }
     }
 
+    // ========== 角色-菜单的相关方法  ==========
+
     @Test
-    public void testGetUserRoleIdsFromCache() {
+    public void testAssignRoleMenu() {
         // 准备参数
-        Long userId = 1L;
-        Collection<Integer> roleStatuses = singleton(CommonStatusEnum.ENABLE.getStatus());
-        // mock 方法 TODO
-        Map<Long, Set<Long>> userRoleCache = MapUtil.<Long, Set<Long>>builder()
-                .put(1L, asSet(10L, 20L)).build();
-//        permissionService.setUserRoleCache(userRoleCache);
-        RoleDO roleDO01 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleFromCache(eq(10L))).thenReturn(roleDO01);
-        RoleDO roleDO02 = randomPojo(RoleDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
-        when(roleService.getRoleFromCache(eq(20L))).thenReturn(roleDO02);
-
-        // 调用 todo
-//        Set<Long> roleIds = permissionService.getUserRoleIdsFromCache(userId, roleStatuses);
-        // 断言 todo
-//        assertEquals(asSet(10L), roleIds);
+        Long roleId = 1L;
+        Set<Long> menuIds = asSet(200L, 300L);
+        // mock 数据
+        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(100L);
+        roleMenuMapper.insert(roleMenu01);
+        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(200L);
+        roleMenuMapper.insert(roleMenu02);
+
+        // 调用
+        permissionService.assignRoleMenu(roleId, menuIds);
+        // 断言
+        List<RoleMenuDO> roleMenuList = roleMenuMapper.selectList();
+        assertEquals(2, roleMenuList.size());
+        assertEquals(1L, roleMenuList.get(0).getRoleId());
+        assertEquals(200L, roleMenuList.get(0).getMenuId());
+        assertEquals(1L, roleMenuList.get(1).getRoleId());
+        assertEquals(300L, roleMenuList.get(1).getMenuId());
+    }
+
+    @Test
+    public void testProcessRoleDeleted() {
+        // 准备参数
+        Long roleId = randomLongId();
+        // mock 数据 UserRole
+        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除
+        userRoleMapper.insert(userRoleDO01);
+        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
+        userRoleMapper.insert(userRoleDO02);
+        // mock 数据 RoleMenu
+        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除
+        roleMenuMapper.insert(roleMenuDO01);
+        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
+        roleMenuMapper.insert(roleMenuDO02);
+
+        // 调用
+        permissionService.processRoleDeleted(roleId);
+        // 断言数据 RoleMenuDO
+        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
+        assertEquals(1, dbRoleMenus.size());
+        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
+        // 断言数据 UserRoleDO
+        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
+        assertEquals(1, dbUserRoles.size());
+        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+    }
+
+    @Test
+    public void testProcessMenuDeleted() {
+        // 准备参数
+        Long menuId = randomLongId();
+        // mock 数据
+        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除
+        roleMenuMapper.insert(roleMenuDO01);
+        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
+        roleMenuMapper.insert(roleMenuDO02);
+
+        // 调用
+        permissionService.processMenuDeleted(menuId);
+        // 断言数据
+        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
+        assertEquals(1, dbRoleMenus.size());
+        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
     }
 
     @Test
@@ -178,27 +225,23 @@ public class PermissionServiceTest extends BaseDbUnitTest {
     }
 
     @Test
-    public void testAssignRoleMenu() {
+    public void testGetMenuRoleIdListByMenuIdFromCache() {
         // 准备参数
-        Long roleId = 1L;
-        Set<Long> menuIds = asSet(200L, 300L);
+        Long menuId = 1L;
         // mock 数据
-        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(100L);
+        RoleMenuDO roleMenu01 = randomPojo(RoleMenuDO.class).setRoleId(100L).setMenuId(1L);
         roleMenuMapper.insert(roleMenu01);
-        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(1L).setMenuId(200L);
+        RoleMenuDO roleMenu02 = randomPojo(RoleMenuDO.class).setRoleId(200L).setMenuId(1L);
         roleMenuMapper.insert(roleMenu02);
 
         // 调用
-        permissionService.assignRoleMenu(roleId, menuIds);
+        Set<Long> roleIds = permissionService.getMenuRoleIdListByMenuIdFromCache(menuId);
         // 断言
-        List<RoleMenuDO> roleMenuList = roleMenuMapper.selectList();
-        assertEquals(2, roleMenuList.size());
-        assertEquals(1L, roleMenuList.get(0).getRoleId());
-        assertEquals(200L, roleMenuList.get(0).getMenuId());
-        assertEquals(1L, roleMenuList.get(1).getRoleId());
-        assertEquals(300L, roleMenuList.get(1).getMenuId());
+        assertEquals(asSet(100L, 200L), roleIds);
     }
 
+    // ========== 用户-角色的相关方法  ==========
+
     @Test
     public void testAssignUserRole() {
         // 准备参数
@@ -221,6 +264,24 @@ public class PermissionServiceTest extends BaseDbUnitTest {
         assertEquals(300L, userRoleDOList.get(1).getRoleId());
     }
 
+    @Test
+    public void testProcessUserDeleted() {
+        // 准备参数
+        Long userId = randomLongId();
+        // mock 数据
+        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(userId)); // 被删除
+        userRoleMapper.insert(userRoleDO01);
+        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
+        userRoleMapper.insert(userRoleDO02);
+
+        // 调用
+        permissionService.processUserDeleted(userId);
+        // 断言数据
+        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
+        assertEquals(1, dbUserRoles.size());
+        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+    }
+
     @Test
     public void testGetUserRoleIdListByUserId() {
         // 准备参数
@@ -238,210 +299,229 @@ public class PermissionServiceTest extends BaseDbUnitTest {
     }
 
     @Test
-    public void testGetUserRoleIdListByRoleIds() {
+    public void testGetUserRoleIdListByUserIdFromCache() {
         // 准备参数
-        Collection<Long> roleIds = asSet(10L, 20L);
+        Long userId = 1L;
         // mock 数据
         UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
         userRoleMapper.insert(userRoleDO01);
-        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(2L).setRoleId(20L));
+        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
         userRoleMapper.insert(roleMenuDO02);
 
         // 调用
-        Set<Long> result = permissionService.getUserRoleIdListByRoleId(roleIds);
+        Set<Long> result = permissionService.getUserRoleIdListByUserIdFromCache(userId);
         // 断言
-        assertEquals(asSet(1L, 2L), result);
+        assertEquals(asSet(10L, 20L), result);
     }
 
     @Test
-    public void testAssignRoleDataScope() {
+    public void testGetUserRoleIdsFromCache() {
         // 准备参数
-        Long roleId = 1L;
-        Integer dataScope = 2;
-        Set<Long> dataScopeDeptIds = asSet(10L, 20L);
+        Long userId = 1L;
+        // mock 数据
+        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
+        userRoleMapper.insert(userRoleDO01);
+        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(20L));
+        userRoleMapper.insert(roleMenuDO02);
 
         // 调用
-        permissionService.assignRoleDataScope(roleId, dataScope, dataScopeDeptIds);
+        Set<Long> result = permissionService.getUserRoleIdListByUserIdFromCache(userId);
         // 断言
-        verify(roleService).updateRoleDataScope(eq(roleId), eq(dataScope), eq(dataScopeDeptIds));
+        assertEquals(asSet(10L, 20L), result);
     }
 
     @Test
-    public void testProcessRoleDeleted() {
+    public void testGetUserRoleIdListByRoleId() {
         // 准备参数
-        Long roleId = randomLongId();
-        // mock 数据 UserRole
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setRoleId(roleId)); // 被删除
+        Collection<Long> roleIds = asSet(10L, 20L);
+        // mock 数据
+        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
         userRoleMapper.insert(userRoleDO01);
-        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
-        userRoleMapper.insert(userRoleDO02);
-        // mock 数据 RoleMenu
-        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(roleId)); // 被删除
-        roleMenuMapper.insert(roleMenuDO01);
-        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
-        roleMenuMapper.insert(roleMenuDO02);
+        UserRoleDO roleMenuDO02 = randomPojo(UserRoleDO.class, o -> o.setUserId(2L).setRoleId(20L));
+        userRoleMapper.insert(roleMenuDO02);
 
         // 调用
-        permissionService.processRoleDeleted(roleId);
-        // 断言数据 RoleMenuDO
-        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
-        assertEquals(1, dbRoleMenus.size());
-        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
-        // 断言数据 UserRoleDO
-        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
-        assertEquals(1, dbUserRoles.size());
-        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+        Set<Long> result = permissionService.getUserRoleIdListByRoleId(roleIds);
+        // 断言
+        assertEquals(asSet(1L, 2L), result);
     }
 
     @Test
-    public void testProcessMenuDeleted() {
-        // 准备参数
-        Long menuId = randomLongId();
-        // mock 数据
-        RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setMenuId(menuId)); // 被删除
-        roleMenuMapper.insert(roleMenuDO01);
-        RoleMenuDO roleMenuDO02 = randomPojo(RoleMenuDO.class); // 不被删除
-        roleMenuMapper.insert(roleMenuDO02);
+    public void testGetEnableUserRoleListByUserIdFromCache() {
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        permissionService.processMenuDeleted(menuId);
-        // 断言数据
-        List<RoleMenuDO> dbRoleMenus = roleMenuMapper.selectList();
-        assertEquals(1, dbRoleMenus.size());
-        assertPojoEquals(dbRoleMenus.get(0), roleMenuDO02);
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户登录的角色
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(100L));
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(200L));
+            RoleDO role01 = randomPojo(RoleDO.class, o -> o.setId(100L)
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            RoleDO role02 = randomPojo(RoleDO.class, o -> o.setId(200L)
+                    .setStatus(CommonStatusEnum.DISABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(asSet(100L, 200L))))
+                    .thenReturn(toList(role01, role02));
+
+            // 调用
+            List<RoleDO> result = permissionService.getEnableUserRoleListByUserIdFromCache(userId);
+            // 断言
+            assertEquals(1, result.size());
+            assertPojoEquals(role01, result.get(0));
+        }
     }
 
+    // ========== 用户-部门的相关方法  ==========
+
     @Test
-    public void testProcessUserDeleted() {
+    public void testAssignRoleDataScope() {
         // 准备参数
-        Long userId = randomLongId();
-        // mock 数据
-        UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(userId)); // 被删除
-        userRoleMapper.insert(userRoleDO01);
-        UserRoleDO userRoleDO02 = randomPojo(UserRoleDO.class); // 不被删除
-        userRoleMapper.insert(userRoleDO02);
+        Long roleId = 1L;
+        Integer dataScope = 2;
+        Set<Long> dataScopeDeptIds = asSet(10L, 20L);
 
         // 调用
-        permissionService.processUserDeleted(userId);
-        // 断言数据
-        List<UserRoleDO> dbUserRoles = userRoleMapper.selectList();
-        assertEquals(1, dbUserRoles.size());
-        assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
+        permissionService.assignRoleDataScope(roleId, dataScope, dataScopeDeptIds);
+        // 断言
+        verify(roleService).updateRoleDataScope(eq(roleId), eq(dataScope), eq(dataScopeDeptIds));
     }
 
     @Test
     public void testGetDeptDataPermission_All() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 用户的角色编号 TODO
-//        permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
-        // mock 获得用户的角色
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())
-                .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
-        when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-        // 断言
-        assertTrue(result.getAll());
-        assertFalse(result.getSelf());
-        assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户的角色编号
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
+            // mock 获得用户的角色
+            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope())
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
+
+            // 调用
+            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
+            // 断言
+            assertTrue(result.getAll());
+            assertFalse(result.getSelf());
+            assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+        }
     }
 
     @Test
     public void testGetDeptDataPermission_DeptCustom() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 用户的角色编号 TODO
-//        permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
-        // mock 获得用户的角色
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())
-                .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
-        when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
-        // mock 部门的返回
-        when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-        // 断言
-        assertFalse(result.getAll());
-        assertFalse(result.getSelf());
-        assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
-        assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
-        assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户的角色编号
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
+            // mock 获得用户的角色
+            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope())
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
+            // mock 部门的返回
+            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
+                    null, null); // 最后返回 null 的目的,看看会不会重复调用
+
+            // 调用
+            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
+            // 断言
+            assertFalse(result.getAll());
+            assertFalse(result.getSelf());
+            assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
+            assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
+            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+        }
     }
 
     @Test
     public void testGetDeptDataPermission_DeptOnly() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 用户的角色编号 TODO
-//        permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
-        // mock 获得用户的角色
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())
-                .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
-        when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
-        // mock 部门的返回
-        when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-        // 断言
-        assertFalse(result.getAll());
-        assertFalse(result.getSelf());
-        assertEquals(1, result.getDeptIds().size());
-        assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户的角色编号
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
+            // mock 获得用户的角色
+            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope())
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
+            // mock 部门的返回
+            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
+                    null, null); // 最后返回 null 的目的,看看会不会重复调用
+
+            // 调用
+            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
+            // 断言
+            assertFalse(result.getAll());
+            assertFalse(result.getSelf());
+            assertEquals(1, result.getDeptIds().size());
+            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+        }
     }
 
     @Test
     public void testGetDeptDataPermission_DeptAndChild() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 用户的角色编号 TODO
-//        permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
-        // mock 获得用户的角色
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())
-                .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
-        when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
-        // mock 部门的返回
-        when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L), null, null); // 最后返回 null 的目的,看看会不会重复调用
-        // mock 方法(部门)TODO
-        DeptDO deptDO = randomPojo(DeptDO.class);
-        when(deptService.getChildDeptIdListFromCache(eq(3L)))
-                .thenReturn(singleton(deptDO.getId()));
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-        // 断言
-        assertFalse(result.getAll());
-        assertFalse(result.getSelf());
-        assertEquals(2, result.getDeptIds().size());
-        assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
-        assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户的角色编号
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
+            // mock 获得用户的角色
+            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope())
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
+            // mock 部门的返回
+            when(userService.getUser(eq(1L))).thenReturn(new AdminUserDO().setDeptId(3L),
+                    null, null); // 最后返回 null 的目的,看看会不会重复调用
+            // mock 方法(部门)
+            DeptDO deptDO = randomPojo(DeptDO.class);
+            when(deptService.getChildDeptIdListFromCache(eq(3L))).thenReturn(singleton(deptDO.getId()));
+
+            // 调用
+            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
+            // 断言
+            assertFalse(result.getAll());
+            assertFalse(result.getSelf());
+            assertEquals(2, result.getDeptIds().size());
+            assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
+            assertTrue(CollUtil.contains(result.getDeptIds(), 3L));
+        }
     }
 
     @Test
     public void testGetDeptDataPermission_Self() {
-        // 准备参数
-        Long userId = 1L;
-        // mock 用户的角色编号 TODO
-//        permissionService.setUserRoleCache(MapUtil.<Long, Set<Long>>builder().put(1L, asSet(2L)).build());
-        // mock 获得用户的角色
-        RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())
-                .setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(singletonList(roleDO));
-        when(roleService.getRoleFromCache(eq(2L))).thenReturn(roleDO);
+        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
+            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PermissionServiceImpl.class)))
+                    .thenReturn(permissionService);
 
-        // 调用
-        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
-        // 断言
-        assertFalse(result.getAll());
-        assertTrue(result.getSelf());
-        assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+            // 准备参数
+            Long userId = 1L;
+            // mock 用户的角色编号
+            userRoleMapper.insert(randomPojo(UserRoleDO.class).setUserId(userId).setRoleId(2L));
+            // mock 获得用户的角色
+            RoleDO roleDO = randomPojo(RoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope())
+                    .setStatus(CommonStatusEnum.ENABLE.getStatus()));
+            when(roleService.getRoleListFromCache(eq(singleton(2L)))).thenReturn(toList(roleDO));
+
+            // 调用
+            DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(userId);
+            // 断言
+            assertFalse(result.getAll());
+            assertTrue(result.getSelf());
+            assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+        }
     }
 
 }