From 10790958ef8295abd20ff2bbf6a12ffca9151312 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 18 Apr 2021 13:43:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20SysUserServiceImplTest=20?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/system/user/index.vue | 2 +- .../service/user/SysUserServiceImpl.java | 30 +- .../service/user/SysUserServiceImplTest.java | 370 ++++++++++++++++-- 3 files changed, 353 insertions(+), 49 deletions(-) diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index 8c836c28f..a9d418a7f 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -362,7 +362,7 @@ export default { created() { this.getList(); this.getTreeselect(); - this.getConfigKey("sys.user.initPassword").then(response => { + this.getConfigKey("sys.user.init-password").then(response => { this.initPassword = response.msg; }); }, diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index 334d0f05f..4e882794a 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -20,7 +20,9 @@ import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.util.collection.CollectionUtils; +import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +44,9 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; @Slf4j public class SysUserServiceImpl implements SysUserService { + @Value("${sys.user.init-password:yudaoyuanma}") + private String userInitPassword; + @Resource private SysUserMapper userMapper; @@ -210,7 +215,8 @@ public class SysUserServiceImpl implements SysUserService { this.checkPostEnable(postIds); } - private void checkUserExists(Long id) { + @VisibleForTesting + void checkUserExists(Long id) { if (id == null) { return; } @@ -220,7 +226,8 @@ public class SysUserServiceImpl implements SysUserService { } } - private void checkUsernameUnique(Long id, String username) { + @VisibleForTesting + void checkUsernameUnique(Long id, String username) { if (StrUtil.isBlank(username)) { return; } @@ -237,7 +244,8 @@ public class SysUserServiceImpl implements SysUserService { } } - private void checkEmailUnique(Long id, String email) { + @VisibleForTesting + void checkEmailUnique(Long id, String email) { if (StrUtil.isBlank(email)) { return; } @@ -254,7 +262,8 @@ public class SysUserServiceImpl implements SysUserService { } } - private void checkMobileUnique(Long id, String mobile) { + @VisibleForTesting + void checkMobileUnique(Long id, String mobile) { if (StrUtil.isBlank(mobile)) { return; } @@ -271,7 +280,8 @@ public class SysUserServiceImpl implements SysUserService { } } - private void checkDeptEnable(Long deptId) { + @VisibleForTesting + void checkDeptEnable(Long deptId) { if (deptId == null) { // 允许不选择 return; } @@ -284,7 +294,8 @@ public class SysUserServiceImpl implements SysUserService { } } - private void checkPostEnable(Set postIds) { + @VisibleForTesting + void checkPostEnable(Set postIds) { if (CollUtil.isEmpty(postIds)) { // 允许不选择 return; } @@ -310,7 +321,8 @@ public class SysUserServiceImpl implements SysUserService { * @param id 用户 id * @param oldPassword 旧密码 */ - private void checkOldPassword(Long id, String oldPassword) { + @VisibleForTesting + void checkOldPassword(Long id, String oldPassword) { SysUserDO user = userMapper.selectById(id); if (user == null) { throw exception(USER_NOT_EXISTS); @@ -340,8 +352,8 @@ public class SysUserServiceImpl implements SysUserService { // 判断如果不存在,在进行插入 SysUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); if (existUser == null) { - // TODO 芋艿:初始密码 - userMapper.insert(SysUserConvert.INSTANCE.convert(importUser)); + userMapper.insert(SysUserConvert.INSTANCE.convert(importUser) + .setPassword(passwordEncoder.encode(userInitPassword))); // 设置默认密码 respVO.getCreateUsernames().add(importUser.getUsername()); return; } diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java index 5c96a46b3..bdb663f82 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImplTest.java @@ -1,15 +1,14 @@ package cn.iocoder.dashboard.modules.system.service.user; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; +import cn.iocoder.dashboard.common.pojo.PageResult; import cn.iocoder.dashboard.modules.infra.service.file.InfFileService; import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportRespVO; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; @@ -20,6 +19,7 @@ import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.util.collection.ArrayUtils; import cn.iocoder.dashboard.util.collection.CollectionUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; import org.junit.jupiter.api.Test; import org.mockito.stubbing.Answer; import org.springframework.boot.test.mock.mockito.MockBean; @@ -28,14 +28,18 @@ import org.springframework.security.crypto.password.PasswordEncoder; import javax.annotation.Resource; import java.io.ByteArrayInputStream; -import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomBytes; import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException; import static cn.iocoder.dashboard.util.RandomUtils.*; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.assertj.core.util.Lists.newArrayList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.*; @@ -228,7 +232,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { } @Test - public void testDeleteUser(){ + public void testDeleteUser_success(){ // mock 数据 SysUserDO dbUser = randomSysUserDO(); userMapper.insert(dbUser); @@ -243,45 +247,333 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { verify(permissionService, times(1)).processUserDeleted(eq(userId)); } + @Test + public void testGetUserPage() { + // mock 数据 + SysUserDO dbUser = initGetUserPageData(); + // 准备参数 + SysUserPageReqVO reqVO = new SysUserPageReqVO(); + reqVO.setUsername("yudao"); + reqVO.setMobile("1560"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setBeginTime(buildTime(2020, 12, 1)); + reqVO.setEndTime(buildTime(2020, 12, 24)); + reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 + // mock 方法 + List deptList = newArrayList(randomPojo(SysDeptDO.class, o -> o.setId(2L))); + when(deptService.getDeptsByParentIdFromCache(eq(reqVO.getDeptId()), eq(true))).thenReturn(deptList); + // 调用 + PageResult pageResult = userService.getUserPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbUser, pageResult.getList().get(0)); + } @Test - public void test_importUsers(){ - SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { // 等会查询到 - o.setName("开发部"); - o.setSort(1); + public void testGetUsers() { + // mock 数据 + SysUserDO dbUser = initGetUserPageData(); + // 准备参数 + SysUserExportReqVO reqVO = new SysUserExportReqVO(); + reqVO.setUsername("yudao"); + reqVO.setMobile("1560"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setBeginTime(buildTime(2020, 12, 1)); + reqVO.setEndTime(buildTime(2020, 12, 24)); + reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 + // mock 方法 + List deptList = newArrayList(randomPojo(SysDeptDO.class, o -> o.setId(2L))); + when(deptService.getDeptsByParentIdFromCache(eq(reqVO.getDeptId()), eq(true))).thenReturn(deptList); + + // 调用 + List list = userService.getUsers(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbUser, list.get(0)); + } + + /** + * 初始化 getUserPage 方法的测试数据 + */ + private SysUserDO initGetUserPageData() { + // mock 数据 + SysUserDO dbUser = randomSysUserDO(o -> { // 等会查询到 + o.setUsername("yudaoyuanma"); + o.setMobile("15601691300"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCreateTime(buildTime(2020, 12, 12)); + o.setDeptId(2L); + }); + userMapper.insert(dbUser); + // 测试 username 不匹配 + userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setUsername("yuanma"))); + // 测试 mobile 不匹配 + userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setMobile("18818260888"))); + // 测试 status 不匹配 + userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime 不匹配 + userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11)))); + // 测试 dept 不匹配 + userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setDeptId(0L))); + return dbUser; + } + + /** + * 情况一,校验不通过,导致插入失败 + */ + @Test + public void testImportUsers_01() { + // 准备参数 + SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class); + // mock 方法 + + // 调用 + SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + // 断言 + assertEquals(0, respVO.getCreateUsernames().size()); + assertEquals(0, respVO.getUpdateUsernames().size()); + assertEquals(1, respVO.getFailureUsernames().size()); + assertEquals(DEPT_NOT_FOUND.getMsg(), respVO.getFailureUsernames().get(importUser.getUsername())); + } + + /** + * 情况二,不存在,进行插入 + */ + @Test + public void testImportUsers_02() { + // 准备参数 + SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 + o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + }); + // mock deptService 的方法 + SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + o.setId(importUser.getDeptId()); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); }); -// int depId = deptMapper.insert(dept); - int depId = 0; + when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); + // mock passwordEncoder 的方法 + when(passwordEncoder.encode(eq("yudaoyuanma"))).thenReturn("java"); + + // 调用 + SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + // 断言 + assertEquals(1, respVO.getCreateUsernames().size()); + SysUserDO user = userMapper.selectByUsername(respVO.getCreateUsernames().get(0)); + assertPojoEquals(importUser, user); + assertEquals("java", user.getPassword()); + assertEquals(0, respVO.getUpdateUsernames().size()); + assertEquals(0, respVO.getFailureUsernames().size()); + } + + /** + * 情况三,存在,但是不强制更新 + */ + @Test + public void testImportUsers_03() { + // mock 数据 + SysUserDO dbUser = randomSysUserDO(); + userMapper.insert(dbUser); // 准备参数 - List list = new ArrayList<>(); - list.add(randomPojo(SysUserImportExcelVO.class, o->{ - o.setDeptId(dept.getId()); - o.setSex(1); - o.setStatus(1); - })); - list.add(randomPojo(SysUserImportExcelVO.class, o->{ - o.setDeptId(dept.getId()); - o.setSex(1); - o.setStatus(1); - })); - list.add(randomPojo(SysUserImportExcelVO.class, o->{ - o.setDeptId(dept.getId()); - o.setSex(1); - o.setStatus(1); - })); - // 批量插入 - SysUserImportRespVO respVO = userService.importUsers(list,false); - System.out.println(respVO.getCreateUsernames().size()); - // 校验结果 - assertEquals(respVO.getCreateUsernames().size(),3); - // 批量更新 - list.get(0).setSex(0); - SysUserImportRespVO respVOUpdate = userService.importUsers(list,true); - System.out.println(respVOUpdate.getUpdateUsernames().size()); - // 校验结果 - assertEquals(respVOUpdate.getUpdateUsernames().size(),3); + SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 + o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setUsername(dbUser.getUsername()); + }); + // mock deptService 的方法 + SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + o.setId(importUser.getDeptId()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); + + // 调用 + SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), false); + // 断言 + assertEquals(0, respVO.getCreateUsernames().size()); + assertEquals(0, respVO.getUpdateUsernames().size()); + assertEquals(1, respVO.getFailureUsernames().size()); + assertEquals(USER_USERNAME_EXISTS.getMsg(), respVO.getFailureUsernames().get(importUser.getUsername())); + } + + /** + * 情况四,存在,强制更新 + */ + @Test + public void testImportUsers_04() { + // mock 数据 + SysUserDO dbUser = randomSysUserDO(); + userMapper.insert(dbUser); + // 准备参数 + SysUserImportExcelVO importUser = randomPojo(SysUserImportExcelVO.class, o -> { + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 + o.setSex(randomEle(SysSexEnum.values()).getSex()); // 保证 sex 的范围 + o.setUsername(dbUser.getUsername()); + }); + // mock deptService 的方法 + SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + o.setId(importUser.getDeptId()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }); + when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); + + // 调用 + SysUserImportRespVO respVO = userService.importUsers(newArrayList(importUser), true); + // 断言 + assertEquals(0, respVO.getCreateUsernames().size()); + assertEquals(1, respVO.getUpdateUsernames().size()); + SysUserDO user = userMapper.selectByUsername(respVO.getUpdateUsernames().get(0)); + assertPojoEquals(importUser, user); + assertEquals(0, respVO.getFailureUsernames().size()); + } + + @Test + public void testCheckUserExists_notExists() { + assertServiceException(() -> userService.checkUserExists(randomLongId()), USER_NOT_EXISTS); + } + + @Test + public void testCheckUsernameUnique_usernameExistsForCreate() { + // 准备参数 + String username = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setUsername(username))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkUsernameUnique(null, username), + USER_USERNAME_EXISTS); + } + + @Test + public void testCheckUsernameUnique_usernameExistsForUpdate() { + // 准备参数 + Long id = randomLongId(); + String username = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setUsername(username))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkUsernameUnique(id, username), + USER_USERNAME_EXISTS); + } + + @Test + public void testCheckEmailUnique_emailExistsForCreate() { + // 准备参数 + String email = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setEmail(email))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkEmailUnique(null, email), + USER_EMAIL_EXISTS); + } + + @Test + public void testCheckEmailUnique_emailExistsForUpdate() { + // 准备参数 + Long id = randomLongId(); + String email = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setEmail(email))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkEmailUnique(id, email), + USER_EMAIL_EXISTS); + } + + @Test + public void testCheckMobileUnique_mobileExistsForCreate() { + // 准备参数 + String mobile = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setMobile(mobile))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkMobileUnique(null, mobile), + USER_MOBILE_EXISTS); + } + + @Test + public void testCheckMobileUnique_mobileExistsForUpdate() { + // 准备参数 + Long id = randomLongId(); + String mobile = randomString(); + // mock 数据 + userMapper.insert(randomSysUserDO(o -> o.setMobile(mobile))); + + // 调用,校验异常 + assertServiceException(() -> userService.checkMobileUnique(id, mobile), + USER_MOBILE_EXISTS); + } + + @Test + public void testCheckDeptEnable_notFound() { + assertServiceException(() -> userService.checkDeptEnable(randomLongId()), + DEPT_NOT_FOUND); + } + + @Test + public void testCheckDeptEnable_notEnable() { + // 准备参数 + Long deptId = randomLongId(); + // mock deptService 的方法 + SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { + o.setId(deptId); + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); + }); + when(deptService.getDept(eq(dept.getId()))).thenReturn(dept); + + // 调用,校验异常 + assertServiceException(() -> userService.checkDeptEnable(deptId), + DEPT_NOT_ENABLE); + } + + @Test + public void testCheckPostEnable_notFound() { + assertServiceException(() -> userService.checkPostEnable(randomSet(Long.class)), + POST_NOT_FOUND); + } + + @Test + public void testCheckPostEnable_notEnable() { + // 准备参数 + Set postIds = randomSet(Long.class); + // mock postService 的方法 + List posts = CollectionUtils.convertList(postIds, postId -> + randomPojo(SysPostDO.class, o -> { + o.setId(postId); + o.setStatus(CommonStatusEnum.DISABLE.getStatus()); + })); + when(postService.getPosts(eq(postIds), isNull())).thenReturn(posts); + + // 调用,校验异常 + assertServiceException(() -> userService.checkPostEnable(postIds), + POST_NOT_ENABLE, CollUtil.getFirst(posts).getName()); + } + + @Test + public void testCheckOldPassword_notExists() { + assertServiceException(() -> userService.checkOldPassword(randomLongId(), randomString()), + USER_NOT_EXISTS); + } + + @Test + public void testCheckOldPassword_passwordFailed() { + // mock 数据 + SysUserDO user = randomSysUserDO(); + userMapper.insert(user); + // 准备参数 + Long id = user.getId(); + String oldPassword = user.getPassword(); + + // 调用,校验异常 + assertServiceException(() -> userService.checkOldPassword(id, oldPassword), + USER_PASSWORD_FAILED); + // 校验调用 + verify(passwordEncoder, times(1)).matches(eq(oldPassword), eq(user.getPassword())); } // ========== 随机对象 ==========