Forráskód Böngészése

完善 MenuService 的单元测试

YunaiV 2 éve
szülő
commit
152fc70e86

+ 2 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java

@@ -62,12 +62,12 @@ public interface MenuService {
     List<MenuDO> getMenuList(MenuListReqVO reqVO);
 
     /**
-     * 获得权限对应的菜单数组
+     * 获得权限对应的菜单编号数组
      *
      * @param permission 权限标识
      * @return 数组
      */
-    List<MenuDO> getMenuListByPermissionFromCache(String permission);
+    List<Long> getMenuIdListByPermissionFromCache(String permission);
 
     /**
      * 获得菜单

+ 16 - 8
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.system.service.permission;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO;
@@ -10,9 +11,9 @@ import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper;
 import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
 import cn.iocoder.yudao.module.system.service.tenant.TenantService;
-import com.baomidou.dynamic.datasource.annotation.Master;
 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.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
@@ -23,6 +24,7 @@ import java.util.Collection;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;
 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
 
@@ -44,6 +46,7 @@ public class MenuServiceImpl implements MenuService {
     private TenantService tenantService;
 
     @Override
+    @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#reqVO.permission")
     public Long createMenu(MenuCreateReqVO reqVO) {
         // 校验父菜单存在
         validateParentMenu(reqVO.getParentId(), null);
@@ -59,6 +62,8 @@ public class MenuServiceImpl implements MenuService {
     }
 
     @Override
+    @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST,
+            allEntries = true) // allEntries 清空所有缓存,因为 permission 如果变更,涉及到新老两个 permission。直接清理,简单有效
     public void updateMenu(MenuUpdateReqVO reqVO) {
         // 校验更新的菜单是否存在
         if (menuMapper.selectById(reqVO.getId()) == null) {
@@ -77,19 +82,21 @@ public class MenuServiceImpl implements MenuService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void deleteMenu(Long menuId) {
+    @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST,
+            allEntries = true) // allEntries 清空所有缓存,因为此时不知道 id 对应的 permission 是多少。直接清理,简单有效
+    public void deleteMenu(Long id) {
         // 校验是否还有子菜单
-        if (menuMapper.selectCountByParentId(menuId) > 0) {
+        if (menuMapper.selectCountByParentId(id) > 0) {
             throw exception(MENU_EXISTS_CHILDREN);
         }
         // 校验删除的菜单是否存在
-        if (menuMapper.selectById(menuId) == null) {
+        if (menuMapper.selectById(id) == null) {
             throw exception(MENU_NOT_EXISTS);
         }
         // 标记删除
-        menuMapper.deleteById(menuId);
+        menuMapper.deleteById(id);
         // 删除授予给角色的权限
-        permissionService.processMenuDeleted(menuId);
+        permissionService.processMenuDeleted(id);
     }
 
     @Override
@@ -112,8 +119,9 @@ public class MenuServiceImpl implements MenuService {
 
     @Override
     @Cacheable(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#permission")
-    public List<MenuDO> getMenuListByPermissionFromCache(String permission) {
-        return menuMapper.selectListByPermission(permission);
+    public List<Long> getMenuIdListByPermissionFromCache(String permission) {
+        List<MenuDO> menus = menuMapper.selectListByPermission(permission);
+        return convertList(menus, MenuDO::getId);
     }
 
     @Override

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

@@ -7,7 +7,6 @@ import cn.hutool.extra.spring.SpringUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
-import cn.iocoder.yudao.framework.tenant.core.db.dynamic.TenantDS;
 import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
@@ -206,19 +205,18 @@ public class PermissionServiceImpl implements PermissionService {
      * @param permission 权限标识
      * @return 是否拥有
      */
-    // TODO 芋艿:要想想咋继续优化
     private boolean hasAnyPermission(List<RoleDO> roles, String permission) {
-        List<MenuDO> menuList = menuService.getMenuListByPermissionFromCache(permission);
+        List<Long> menuIds = menuService.getMenuIdListByPermissionFromCache(permission);
         // 采用严格模式,如果权限找不到对应的 Menu 的话,也认为没有权限
-        if (CollUtil.isEmpty(menuList)) {
+        if (CollUtil.isEmpty(menuIds)) {
             return false;
         }
 
         // 判断是否有权限
         Set<Long> roleIds = convertSet(roles, RoleDO::getId);
-        for (MenuDO menu : menuList) {
+        for (Long menuId : menuIds) {
             // 拥有该角色的菜单编号数组
-            Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menu.getId());
+            Set<Long> menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menuId);
             // 如果有交集,说明有权限
             if (CollUtil.containsAny(menuRoleIds, roleIds)) {
                 return true;

+ 14 - 126
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java

@@ -8,10 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUp
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
 import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper;
 import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
-import cn.iocoder.yudao.module.system.mq.producer.permission.MenuProducer;
 import cn.iocoder.yudao.module.system.service.tenant.TenantService;
-import com.google.common.collect.LinkedListMultimap;
-import com.google.common.collect.Multimap;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
@@ -26,8 +23,6 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
 import static cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO.ID_ROOT;
 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonList;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -46,35 +41,12 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @MockBean
     private PermissionService permissionService;
     @MockBean
-    private MenuProducer menuProducer;
-    @MockBean
     private TenantService tenantService;
 
-    @Test
-    public void testInitLocalCache_success() {
-        MenuDO menuDO1 = randomPojo(MenuDO.class);
-        menuMapper.insert(menuDO1);
-        MenuDO menuDO2 = randomPojo(MenuDO.class);
-        menuMapper.insert(menuDO2);
-
-        // 调用
-        menuService.initLocalCache();
-        // 校验 menuCache 缓存
-        Map<Long, MenuDO> menuCache = menuService.getMenuCache();
-        assertEquals(2, menuCache.size());
-        assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId()));
-        assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId()));
-        // 校验 permissionMenuCache 缓存
-        Multimap<String, MenuDO> permissionMenuCache = menuService.getPermissionMenuCache();
-        assertEquals(2, permissionMenuCache.size());
-        assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission()));
-        assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission()));
-    }
-
     @Test
     public void testCreateMenu_success() {
         // mock 数据(构造父菜单)
-        MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU,
+        MenuDO menuDO = buildMenuDO(MenuTypeEnum.MENU,
                 "parent", 0L);
         menuMapper.insert(menuDO);
         Long parentId = menuDO.getId();
@@ -89,14 +61,12 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
         // 校验记录的属性是否正确
         MenuDO dbMenu = menuMapper.selectById(menuId);
         assertPojoEquals(reqVO, dbMenu);
-        // 校验调用
-        verify(menuProducer).sendMenuRefreshMessage();
     }
 
     @Test
     public void testUpdateMenu_success() {
         // mock 数据(构造父子菜单)
-        MenuDO sonMenuDO = initParentAndSonMenu();
+        MenuDO sonMenuDO = createParentAndSonMenu();
         Long sonId = sonMenuDO.getId();
         // 准备参数
         MenuUpdateReqVO reqVO = randomPojo(MenuUpdateReqVO.class, o -> {
@@ -111,8 +81,6 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
         // 校验记录的属性是否正确
         MenuDO dbMenu = menuMapper.selectById(sonId);
         assertPojoEquals(reqVO, dbMenu);
-        // 校验调用
-        verify(menuProducer).sendMenuRefreshMessage();
     }
 
     @Test
@@ -137,7 +105,6 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
         MenuDO dbMenuDO = menuMapper.selectById(id);
         assertNull(dbMenuDO);
         verify(permissionService).processMenuDeleted(id);
-        verify(menuProducer).sendMenuRefreshMessage();
     }
 
     @Test
@@ -149,7 +116,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testDeleteMenu_existChildren() {
         // mock 数据(构造父子菜单)
-        MenuDO sonMenu = initParentAndSonMenu();
+        MenuDO sonMenu = createParentAndSonMenu();
         // 准备参数
         Long parentId = sonMenu.getParentId();
 
@@ -218,85 +185,6 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
         assertPojoEquals(menu100, result.get(0));
     }
 
-    @Test
-    public void testListMenusFromCache_withoutId() {
-        // mock 缓存
-        Map<Long, MenuDO> menuCache = new HashMap<>();
-        // 可被匹配
-        MenuDO menuDO = randomPojo(MenuDO.class, o -> o.setId(1L)
-                .setType(MenuTypeEnum.MENU.getType()).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        menuCache.put(menuDO.getId(), menuDO);
-        // 测试 type 不匹配
-        menuCache.put(3L, randomPojo(MenuDO.class, o -> o.setId(3L)
-                .setType(MenuTypeEnum.BUTTON.getType()).setStatus(CommonStatusEnum.ENABLE.getStatus())));
-        // 测试 status 不匹配
-        menuCache.put(4L, randomPojo(MenuDO.class, o -> o.setId(4L)
-                .setType(MenuTypeEnum.MENU.getType()).setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        menuService.setMenuCache(menuCache);
-        // 准备参数
-        Collection<Integer> menuTypes = singletonList(MenuTypeEnum.MENU.getType());
-        Collection<Integer> menusStatuses = singletonList(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        List<MenuDO> list = menuService.getMenuListFromCache(menuTypes, menusStatuses);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(menuDO, list.get(0));
-    }
-
-    @Test
-    public void testListMenusFromCache_withId() {
-        // mock 缓存
-        Map<Long, MenuDO> menuCache = new HashMap<>();
-        // 可被匹配
-        MenuDO menuDO = randomPojo(MenuDO.class, o -> o.setId(1L)
-                .setType(MenuTypeEnum.MENU.getType()).setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        menuCache.put(menuDO.getId(), menuDO);
-        // 测试 id 不匹配
-        menuCache.put(2L, randomPojo(MenuDO.class, o -> o.setId(2L)
-                .setType(MenuTypeEnum.MENU.getType()).setStatus(CommonStatusEnum.ENABLE.getStatus())));
-        // 测试 type 不匹配
-        menuCache.put(3L, randomPojo(MenuDO.class, o -> o.setId(3L)
-                .setType(MenuTypeEnum.BUTTON.getType()).setStatus(CommonStatusEnum.ENABLE.getStatus())));
-        // 测试 status 不匹配
-        menuCache.put(4L, randomPojo(MenuDO.class, o -> o.setId(4L)
-                .setType(MenuTypeEnum.MENU.getType()).setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        menuService.setMenuCache(menuCache);
-        // 准备参数
-        Collection<Long> menuIds = asList(1L, 3L, 4L);
-        Collection<Integer> menuTypes = singletonList(MenuTypeEnum.MENU.getType());
-        Collection<Integer> menusStatuses = singletonList(CommonStatusEnum.ENABLE.getStatus());
-
-        // 调用
-        List<MenuDO> list = menuService.getMenuListFromCache(menuIds, menuTypes, menusStatuses);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(menuDO, list.get(0));
-    }
-
-    @Test
-    public void testGetMenuListByPermissionFromCache() {
-        // mock 缓存
-        Multimap<String, MenuDO> permissionMenuCache = LinkedListMultimap.create();
-        // 可被匹配
-        MenuDO menuDO01 = randomPojo(MenuDO.class, o -> o.setId(1L).setPermission("123"));
-        permissionMenuCache.put(menuDO01.getPermission(), menuDO01);
-        MenuDO menuDO02 = randomPojo(MenuDO.class, o -> o.setId(2L).setPermission("123"));
-        permissionMenuCache.put(menuDO02.getPermission(), menuDO02);
-        // 不可匹配
-        permissionMenuCache.put("456", randomPojo(MenuDO.class, o -> o.setId(3L).setPermission("456")));
-        menuService.setPermissionMenuCache(permissionMenuCache);
-        // 准备参数
-        String permission = "123";
-
-        // 调用
-        List<MenuDO> list = menuService.getMenuListByPermissionFromCache(permission);
-        // 断言
-        assertEquals(2, list.size());
-        assertPojoEquals(menuDO01, list.get(0));
-        assertPojoEquals(menuDO02, list.get(1));
-    }
-
     @Test
     public void testGetMenu() {
         // mock 数据
@@ -314,7 +202,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testValidateParentMenu_success() {
         // mock 数据
-        MenuDO menuDO = createMenuDO(MenuTypeEnum.MENU, "parent", 0L);
+        MenuDO menuDO = buildMenuDO(MenuTypeEnum.MENU, "parent", 0L);
         menuMapper.insert(menuDO);
         // 准备参数
         Long parentId = menuDO.getId();
@@ -340,7 +228,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testValidateParentMenu_parentTypeError() {
         // mock 数据
-        MenuDO menuDO = createMenuDO(MenuTypeEnum.BUTTON, "parent", 0L);
+        MenuDO menuDO = buildMenuDO(MenuTypeEnum.BUTTON, "parent", 0L);
         menuMapper.insert(menuDO);
         // 准备参数
         Long parentId = menuDO.getId();
@@ -353,7 +241,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testValidateMenu_success() {
         // mock 父子菜单
-        MenuDO sonMenu = initParentAndSonMenu();
+        MenuDO sonMenu = createParentAndSonMenu();
         // 准备参数
         Long parentId = sonMenu.getParentId();
         Long otherSonMenuId = randomLongId();
@@ -366,7 +254,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     @Test
     public void testValidateMenu_sonMenuNameDuplicate() {
         // mock 父子菜单
-        MenuDO sonMenu = initParentAndSonMenu();
+        MenuDO sonMenu = createParentAndSonMenu();
         // 准备参数
         Long parentId = sonMenu.getParentId();
         Long otherSonMenuId = randomLongId();
@@ -380,26 +268,26 @@ public class MenuServiceImplTest extends BaseDbUnitTest {
     // ====================== 初始化方法 ======================
 
     /**
-     * 构造父子菜单,返回子菜单
+     * 插入父子菜单,返回子菜单
      *
      * @return 子菜单
      */
-    private MenuDO initParentAndSonMenu() {
+    private MenuDO createParentAndSonMenu() {
         // 构造父子菜单
-        MenuDO parentMenuDO = createMenuDO(MenuTypeEnum.MENU, "parent", ID_ROOT);
+        MenuDO parentMenuDO = buildMenuDO(MenuTypeEnum.MENU, "parent", ID_ROOT);
         menuMapper.insert(parentMenuDO);
         // 构建子菜单
-        MenuDO sonMenuDO = createMenuDO(MenuTypeEnum.MENU, "testSonName",
+        MenuDO sonMenuDO = buildMenuDO(MenuTypeEnum.MENU, "testSonName",
                 parentMenuDO.getParentId());
         menuMapper.insert(sonMenuDO);
         return sonMenuDO;
     }
 
-    private MenuDO createMenuDO(MenuTypeEnum type, String name, Long parentId) {
-        return createMenuDO(type, name, parentId, randomCommonStatus());
+    private MenuDO buildMenuDO(MenuTypeEnum type, String name, Long parentId) {
+        return buildMenuDO(type, name, parentId, randomCommonStatus());
     }
 
-    private MenuDO createMenuDO(MenuTypeEnum type, String name, Long parentId, Integer status) {
+    private MenuDO buildMenuDO(MenuTypeEnum type, String name, Long parentId, Integer status) {
         return randomPojo(MenuDO.class, o -> o.setId(null).setName(name).setParentId(parentId)
                 .setType(type.getType()).setStatus(status));
     }