1、完善DeptServiceImpl单元测试覆盖率90%;2、新增security mock能力;3、移除postservice相关代码;4、移除部分无用模块的单测代码;

This commit is contained in:
gaoqr
2025-09-10 16:54:02 +08:00
parent ecae82b507
commit 283759c90d
32 changed files with 586 additions and 1643 deletions
@@ -2,16 +2,26 @@ package com.cf.imes.module.system.service.dept;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.util.object.ObjectUtils;
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.framework.security.test.WithMockLoginUser;
import com.cf.imes.framework.test.core.ut.BaseDbAndRedisUnitTest;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.DeptDO;
import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO;
import com.cf.imes.module.system.dal.mysql.dept.DeptMapper;
import com.cf.imes.module.system.service.user.AdminUserService;
import com.cf.imes.module.system.util.redis.SystemRedisUtils;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -19,8 +29,9 @@ import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.when;
/**
* {@link DeptServiceImpl} 的单元测试类
@@ -28,13 +39,19 @@ import static org.junit.jupiter.api.Assertions.*;
* @author niudehua
*/
@Import(DeptServiceImpl.class)
public class DeptServiceImplTest extends BaseDbUnitTest {
public class DeptServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private DeptServiceImpl deptService;
@Resource
private DeptMapper deptMapper;
@MockitoBean
private AdminUserService userService;
@MockitoBean
private SystemRedisUtils systemRedisUtils;
@Test
public void testCreateDept() {
// 准备参数
@@ -54,7 +71,8 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
}
@Test
public void testUpdateDept() {
@WithMockLoginUser
public void testUpdateDept_enable() {
// mock 数据
DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus()));
deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
@@ -63,7 +81,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
// 设置更新的 ID
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setId(dbDeptDO.getId());
o.setStatus(randomCommonStatus());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
});
// 调用
@@ -74,6 +92,50 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
}
@Test
@WithMockLoginUser
public void testUpdateDept_disable() {
// mock 数据
DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus()));
deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
// 准备参数
DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
// 设置更新的 ID
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setId(dbDeptDO.getId());
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
});
// 调用
deptService.updateDept(reqVO);
// 校验是否更新正确
DeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, deptDO);
}
@Test
@WithMockLoginUser
public void testUpdateDept_parentDeptUserOperNotAllow() {
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
// mock 数据
DeptDO parentDeptDO = randomPojo(DeptDO.class, o -> o.setId(randomLongId()));
DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> {
o.setId(loginUser.getDeptId());
o.setParentId(parentDeptDO.getId());
});
deptMapper.insert(parentDeptDO);
deptMapper.insert(dbDeptDO);
// 准备参数
DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> {
o.setParentId(DeptDO.PARENT_ID_ROOT);
o.setId(parentDeptDO.getId());
});
assertServiceException(() -> deptService.updateDept(reqVO),
PARENT_DEPT_USER_OPER_NOT_ALLOW);
}
@Test
@WithMockLoginUser
public void testDeleteDept_success() {
// mock 数据
DeptDO dbDeptDO = randomPojo(DeptDO.class);
@@ -87,6 +149,36 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
assertNull(deptMapper.selectById(id));
}
@Test
@WithMockLoginUser
public void testDeleteDept_deptUserOperNotAllow() {
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
// mock 数据
DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setId(loginUser.getDeptId()));
deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDeptDO.getId();
assertServiceException(() -> deptService.deleteDept(id),
DEPT_USER_OPER_NOT_ALLOW);
}
@Test
@WithMockLoginUser
public void testDeleteDept_deptUserExists(){
// mock 数据
DeptDO dbDeptDO = randomPojo(DeptDO.class);
deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDeptDO.getId();
when(userService.getUserListByDeptIds(anyList()))
.thenReturn(Collections.singletonList(new AdminUserDO()));
assertServiceException(() -> deptService.deleteDept(id),
DEPT_EXISTS_USER);
}
@Test
public void testDeleteDept_exitsChildren() {
// mock 数据
@@ -104,6 +196,22 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN);
}
@Test
public void testValidateDeptExists_idIsNull() {
// 调用,不抛异常
deptService.validateDeptExists(null);
}
@Test
public void testValidateDeptExists_exists() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class);
deptMapper.insert(deptDO);
// 调用,不抛异常
deptService.validateDeptExists(deptDO.getId());
}
@Test
public void testValidateDeptExists_notFound() {
// 准备参数
@@ -123,15 +231,73 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
DEPT_PARENT_ERROR);
}
@Test
public void testValidateParentDept_parentNotExists() {
Long id = randomLongId();
Long parentId = randomLongId(); // 假设不存在的 ID
assertServiceException(() -> deptService.validateParentDept(id, parentId),
DEPT_PARENT_NOT_EXITS);
}
@Test
public void testValidateParentDept_parentDisabled() {
DeptDO parentDept = randomPojo(DeptDO.class);
parentDept.setStatus(CommonStatusEnum.DISABLE.getStatus());
deptMapper.insert(parentDept);
Long id = randomLongId();
Long parentId = parentDept.getId();
assertServiceException(() -> deptService.validateParentDept(id, parentId),
PARENT_DEPT_DISABLE, parentDept.getName());
}
@Test
public void testValidateParentDept_multiLevelParentDisabled() {
// 构造三级部门:grandParent -> parent -> child
DeptDO grandParent = randomPojo(DeptDO.class);
grandParent.setStatus(CommonStatusEnum.DISABLE.getStatus());
deptMapper.insert(grandParent);
DeptDO parent = randomPojo(DeptDO.class, o -> o.setParentId(grandParent.getId()));
parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(parent);
Long id = randomLongId();
Long parentId = parent.getId();
assertServiceException(() -> deptService.validateParentDept(id, parentId),
PARENT_DEPT_DISABLE, grandParent.getName());
}
@Test
public void testValidateParentDept_validHierarchy() {
DeptDO grandParent = randomPojo(DeptDO.class);
grandParent.setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(grandParent);
DeptDO parent = randomPojo(DeptDO.class, o -> o.setParentId(grandParent.getId()));
parent.setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(parent);
Long id = randomLongId();
Long parentId = parent.getId();
// 不抛异常
deptService.validateParentDept(id, parentId);
}
@Test
public void testValidateParentDept_parentIsChild() {
// mock 数据(父节点)
DeptDO parentDept = randomPojo(DeptDO.class);
parentDept.setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(parentDept);
// mock 数据(子节点)
DeptDO childDept = randomPojo(DeptDO.class, o -> {
o.setParentId(parentDept.getId());
});
childDept.setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(childDept);
// 准备参数
@@ -152,12 +318,64 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
Long id = randomLongId();
Long parentId = deptDO.getParentId();
String name = deptDO.getName();
Long organId = deptDO.getOrganId();
// 调用, 并断言异常
assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, null),
assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, organId),
DEPT_NAME_DUPLICATE);
}
@Test
public void testValidateDeptNameUnique_newDeptDuplicate() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class);
deptMapper.insert(deptDO);
// 准备参数:id = null,模拟新增
Long id = null;
Long parentId = deptDO.getParentId();
String name = deptDO.getName();
Long organId = deptDO.getOrganId();
// 调用,并断言异常
assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, organId),
DEPT_NAME_DUPLICATE);
}
@Test
public void testValidateDeptNameUnique_updateOtherDeptDuplicate() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class);
deptMapper.insert(deptDO);
// 准备参数:id 不同,模拟更新到重名部门
Long id = randomLongId(); // 与 deptDO 的 id 不同
Long parentId = deptDO.getParentId();
String name = deptDO.getName();
Long organId = deptDO.getOrganId();
// 调用,并断言异常
assertServiceException(() -> deptService.validateDeptNameUnique(id, parentId, name, organId),
DEPT_NAME_DUPLICATE);
}
@Test
public void testValidateDeptNameUnique_updateSameDept() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class);
deptMapper.insert(deptDO);
// 准备参数:id 相同,表示更新自己
Long id = deptDO.getId();
Long parentId = deptDO.getParentId();
String name = deptDO.getName();
Long organId = deptDO.getOrganId();
// 调用,不抛异常
deptService.validateDeptNameUnique(id, parentId, name, organId);
}
@Test
public void testGetDept() {
// mock 数据
@@ -191,11 +409,47 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
}
@Test
public void testGetDeptList_reqVO() {
public void testGetDeptList_emptyids() {
assertEquals(0, deptService.getDeptList(Collections.emptyList()).size());
}
@Test
@WithMockLoginUser(isSuperAdmin = true)
public void testGetDeptList_superadmin_reqVO() {
Long organId = SecurityFrameworkUtils.getUserOrganId();
// mock 数据
DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到
o.setName("开发部");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setOrganId(organId);
});
deptMapper.insert(dept);
// 测试 name 不匹配
deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setName("")));
// 测试 status 不匹配
deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 准备参数
DeptListReqVO reqVO = new DeptListReqVO();
reqVO.setName("");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
reqVO.setOrganId(organId);
// 调用
List<DeptDO> sysDeptDOS = deptService.getDeptList(reqVO);
// 断言
assertEquals(1, sysDeptDOS.size());
assertPojoEquals(dept, sysDeptDOS.get(0));
}
@Test
@WithMockLoginUser
public void testGetDeptList_commonuser_reqVO() {
Long organId = SecurityFrameworkUtils.getUserOrganId();
// mock 数据
DeptDO dept = randomPojo(DeptDO.class, o -> { // 等会查询到
o.setName("开发部");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setOrganId(organId);
});
deptMapper.insert(dept);
// 测试 name 不匹配
@@ -261,36 +515,125 @@ public class DeptServiceImplTest extends BaseDbUnitTest {
}
@Test
public void testValidateDeptList_success() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.ENABLE.getStatus());
deptMapper.insert(deptDO);
// 准备参数
List<Long> ids = singletonList(deptDO.getId());
public void testValidDept_NotFound() {
// 部门不存在
assertServiceException(() -> deptService.validDept(1L), DEPT_NOT_FOUND);
}
@Test
public void testValidDept_Disabled() {
// 部门状态不可用
DeptDO disableDbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
deptMapper.insert(disableDbDeptDO);
assertServiceException(() -> deptService.validDept(disableDbDeptDO.getId()), DEPT_DISABLE, disableDbDeptDO.getName());
}
@Test
public void testValidDept_ParentNotFound() {
DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
});
deptMapper.insert(enabledbDeptDO);
assertServiceException(() -> deptService.validDept(enabledbDeptDO.getId()), DEPT_PARENT_NOT_EXITS);
}
@Test
public void testValidDept_ParentDisabled() {
DeptDO disabledParentDetpDO = randomPojo(DeptDO.class, o -> {
o.setId(null);
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
});
deptMapper.insert(disabledParentDetpDO);
DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
o.setId(null);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setParentId(disabledParentDetpDO.getId());
});
deptMapper.insert(enabledbDeptDO);
assertServiceException(() -> deptService.validDept(enabledbDeptDO.getId()), DEPT_DISABLE, disabledParentDetpDO.getName());
}
@Test
public void testValidDept_success() {
DeptDO disabledParentDetpDO = randomPojo(DeptDO.class, o -> {
o.setId(null);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setParentId(DeptDO.PARENT_ID_ROOT);
});
deptMapper.insert(disabledParentDetpDO);
DeptDO enabledbDeptDO = randomPojo(DeptDO.class, o -> {
o.setId(null);
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setParentId(disabledParentDetpDO.getId());
});
deptMapper.insert(enabledbDeptDO);
// 调用,无需断言
deptService.validateDeptList(ids);
assertDoesNotThrow(()-> deptService.validDept(enabledbDeptDO.getId()));
}
@Test
public void testValidateDeptList_notFound() {
// 准备参数
List<Long> ids = singletonList(randomLongId());
// 调用, 并断言异常
assertServiceException(() -> deptService.validateDeptList(ids), DEPT_NOT_FOUND);
public void removeUnowndDept_empty() {
List<DeptDO> deptDOS = deptService.removeUnowndDept(Collections.emptyList());
assertEquals(deptDOS.size(), 0);
}
@Test
public void testValidateDeptList_notEnable() {
// mock 数据
DeptDO deptDO = randomPojo(DeptDO.class).setStatus(CommonStatusEnum.DISABLE.getStatus());
deptMapper.insert(deptDO);
// 准备参数
List<Long> ids = singletonList(deptDO.getId());
// 调用, 并断言异常
assertServiceException(() -> deptService.validateDeptList(ids), DEPT_NOT_ENABLE, deptDO.getName());
public void removeUnowndDept_success() {
DeptDO oneParent = randomPojo(DeptDO.class, o -> o.setParentId(DeptDO.PARENT_ID_ROOT));
DeptDO onechild1 = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
DeptDO onechild2 = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
List<DeptDO> paramDeptList = List.of(oneParent, onechild1, onechild2);
List<DeptDO> deptDOS = deptService.removeUnowndDept(paramDeptList);
assertEquals(deptDOS.size(), paramDeptList.size());
}
@Test
public void removeUnowndDept_ParentNotFound() {
DeptDO oneParent = randomPojo(DeptDO.class, o -> o.setParentId(DeptDO.PARENT_ID_ROOT));
DeptDO one = randomPojo(DeptDO.class, o -> o.setParentId(oneParent.getId()));
DeptDO two = randomPojo(DeptDO.class);
List<DeptDO> paramDeptList = List.of(oneParent, one, two);
List<DeptDO> deptDOS = deptService.removeUnowndDept(paramDeptList);
assertNotEquals(deptDOS.size(), paramDeptList.size());
}
@Test
public void getAllInvalidDeptIds_success() {
Long organId = randomLongId();
DeptDO oneParent = randomPojo(DeptDO.class, o -> {
o.setId(randomLongId());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setOrganId(organId);
o.setParentId(DeptDO.PARENT_ID_ROOT);
});
Long parentId = oneParent.getId();
DeptDO one = randomPojo(DeptDO.class, o -> {
o.setStatus(randomCommonStatus());
o.setOrganId(organId);
o.setParentId(parentId);
});
DeptDO two = randomPojo(DeptDO.class, o -> {
o.setStatus(randomCommonStatus());
o.setOrganId(organId);
o.setParentId(parentId);
});
DeptDO three = randomPojo(DeptDO.class, o -> {
o.setStatus(randomCommonStatus());
o.setOrganId(organId);
o.setParentId(parentId);
});
List<DeptDO> deptDOS = List.of(oneParent, one, two, three);
// 批量插入
deptMapper.insertBatch(deptDOS);
long disableCount = deptDOS.stream().filter(o -> CommonStatusEnum.DISABLE.getStatus().equals(o.getStatus())).count();
Set<Long> allInvalidDeptIds = deptService.getAllInvalidDeptIds(organId);
assertEquals(disableCount, allInvalidDeptIds.size());
OrganContextHolder.setOrganId(organId);
Set<Long> noOrganAllInvalidDeptIds = deptService.getAllInvalidDeptIds(null);
assertEquals(disableCount, noOrganAllInvalidDeptIds.size());
}
}
@@ -1,248 +0,0 @@
package com.cf.imes.module.system.service.dept;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.collection.ArrayUtils;
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostPageReqVO;
import com.cf.imes.module.system.controller.admin.dept.vo.post.PostSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.dept.PostDO;
import com.cf.imes.module.system.dal.mysql.dept.PostMapper;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link PostServiceImpl} 的单元测试类
*
* @author niudehua
*/
@Import(PostServiceImpl.class)
public class PostServiceImplTest extends BaseDbUnitTest {
@Resource
private PostServiceImpl postService;
@Resource
private PostMapper postMapper;
@Test
public void testCreatePost_success() {
// 准备参数
PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class,
o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()))
.setId(null); // 防止 id 被设置
// 调用
Long postId = postService.createPost(reqVO);
// 断言
assertNotNull(postId);
// 校验记录的属性是否正确
PostDO post = postMapper.selectById(postId);
assertPojoEquals(reqVO, post, "id");
}
@Test
public void testUpdatePost_success() {
// mock 数据
PostDO postDO = randomPostDO();
postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
// 准备参数
PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> {
// 设置更新的 ID
o.setId(postDO.getId());
o.setStatus(randomEle(CommonStatusEnum.values()).getStatus());
});
// 调用
postService.updatePost(reqVO);
// 校验是否更新正确
PostDO post = postMapper.selectById(reqVO.getId());
assertPojoEquals(reqVO, post);
}
@Test
public void testDeletePost_success() {
// mock 数据
PostDO postDO = randomPostDO();
postMapper.insert(postDO);
// 准备参数
Long id = postDO.getId();
// 调用
postService.deletePost(id);
assertNull(postMapper.selectById(id));
}
@Test
public void testValidatePost_notFoundForDelete() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> postService.deletePost(id), POST_NOT_FOUND);
}
@Test
public void testValidatePost_nameDuplicateForCreate() {
// mock 数据
PostDO postDO = randomPostDO();
postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
// 准备参数
PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class,
// 模拟 name 重复
o -> o.setName(postDO.getName()));
assertServiceException(() -> postService.createPost(reqVO), POST_NAME_DUPLICATE);
}
@Test
public void testValidatePost_codeDuplicateForUpdate() {
// mock 数据
PostDO postDO = randomPostDO();
postMapper.insert(postDO);
// mock 数据:稍后模拟重复它的 code
PostDO codePostDO = randomPostDO();
postMapper.insert(codePostDO);
// 准备参数
PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> {
// 设置更新的 ID
o.setId(postDO.getId());
// 模拟 code 重复
o.setCode(codePostDO.getCode());
});
// 调用, 并断言异常
assertServiceException(() -> postService.updatePost(reqVO), POST_CODE_DUPLICATE);
}
@Test
public void testGetPostPage() {
// mock 数据
PostDO postDO = randomPojo(PostDO.class, o -> {
o.setName("码仔");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
});
postMapper.insert(postDO);
// 测试 name 不匹配
postMapper.insert(cloneIgnoreId(postDO, o -> o.setName("程序员")));
// 测试 status 不匹配
postMapper.insert(cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 准备参数
PostPageReqVO reqVO = new PostPageReqVO();
reqVO.setName("");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
// 调用
PageResult<PostDO> pageResult = postService.getPostPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(postDO, pageResult.getList().get(0));
}
@Test
public void testGetPostList() {
// mock 数据
PostDO postDO01 = randomPojo(PostDO.class);
postMapper.insert(postDO01);
// 测试 id 不匹配
PostDO postDO02 = randomPojo(PostDO.class);
postMapper.insert(postDO02);
// 准备参数
List<Long> ids = singletonList(postDO01.getId());
// 调用
List<PostDO> list = postService.getPostList(ids);
// 断言
assertEquals(1, list.size());
assertPojoEquals(postDO01, list.get(0));
}
@Test
public void testGetPostList_idsAndStatus() {
// mock 数据
PostDO postDO01 = randomPojo(PostDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
postMapper.insert(postDO01);
// 测试 status 不匹配
PostDO postDO02 = randomPojo(PostDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
postMapper.insert(postDO02);
// 准备参数
List<Long> ids = Arrays.asList(postDO01.getId(), postDO02.getId());
// 调用
List<PostDO> list = postService.getPostList(ids, singletonList(CommonStatusEnum.ENABLE.getStatus()),1L);
// 断言
assertEquals(1, list.size());
assertPojoEquals(postDO01, list.get(0));
}
@Test
public void testGetPost() {
// mock 数据
PostDO dbPostDO = randomPostDO();
postMapper.insert(dbPostDO);
// 准备参数
Long id = dbPostDO.getId();
// 调用
PostDO post = postService.getPost(id);
// 断言
assertNotNull(post);
assertPojoEquals(dbPostDO, post);
}
@Test
public void testValidatePostList_success() {
// mock 数据
PostDO postDO = randomPostDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
postMapper.insert(postDO);
// 准备参数
List<Long> ids = singletonList(postDO.getId());
// 调用,无需断言
postService.validatePostList(ids);
}
@Test
public void testValidatePostList_notFound() {
// 准备参数
List<Long> ids = singletonList(randomLongId());
// 调用, 并断言异常
assertServiceException(() -> postService.validatePostList(ids), POST_NOT_FOUND);
}
@Test
public void testValidatePostList_notEnable() {
// mock 数据
PostDO postDO = randomPostDO().setStatus(CommonStatusEnum.DISABLE.getStatus());
postMapper.insert(postDO);
// 准备参数
List<Long> ids = singletonList(postDO.getId());
// 调用, 并断言异常
assertServiceException(() -> postService.validatePostList(ids), POST_NOT_ENABLE,
postDO.getName());
}
@SafeVarargs
private static PostDO randomPostDO(Consumer<PostDO>... consumers) {
Consumer<PostDO> consumer = (o) -> {
o.setStatus(randomCommonStatus()); // 保证 status 的范围
};
return randomPojo(PostDO.class, ArrayUtils.append(consumer, consumers));
}
}
@@ -1,472 +0,0 @@
package com.cf.imes.module.system.service.social;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.util.ReflectUtil;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.enums.UserTypeEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
import com.cf.imes.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
import com.cf.imes.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.social.SocialClientDO;
import com.cf.imes.module.system.dal.mysql.social.SocialClientMapper;
import com.cf.imes.module.system.enums.social.SocialTypeEnum;
import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
import com.cf.imes.module.system.framework.justauth.core.AuthRequestFactory;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.StringRedisTemplate;
import jakarta.annotation.Resource;
import static com.cf.imes.framework.test.core.util.RandomUtils.*;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* {@link SocialClientServiceImpl} 的单元测试类
*
* @author 晨丰科技
*/
@Import(SocialClientServiceImpl.class)
public class SocialClientServiceImplTest extends BaseDbUnitTest {
@Resource
private SocialClientServiceImpl socialClientService;
@Resource
private SocialClientMapper socialClientMapper;
@MockBean
private AuthRequestFactory authRequestFactory;
@MockBean
private WxMpService wxMpService;
@MockBean
private WxMpProperties wxMpProperties;
@MockBean
private StringRedisTemplate stringRedisTemplate;
@MockBean
private WxMaService wxMaService;
@MockBean
private WxMaProperties wxMaProperties;
@Test
public void testGetAuthorizeUrl() {
try (MockedStatic<AuthStateUtils> authStateUtilsMock = mockStatic(AuthStateUtils.class)) {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String redirectUri = "sss";
// mock 获得对应的 AuthRequest 实现
AuthRequest authRequest = mock(AuthRequest.class);
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// mock 方法
authStateUtilsMock.when(AuthStateUtils::createState).thenReturn("aoteman");
when(authRequest.authorize(eq("aoteman"))).thenReturn("https://www.cf.com?redirect_uri=yyy");
// 调用
String url = socialClientService.getAuthorizeUrl(socialType, userType, redirectUri);
// 断言
assertEquals("https://www.cf.com?redirect_uri=sss", url);
}
}
@Test
public void testAuthSocialUser_success() {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String code = randomString();
String state = randomString();
// mock 方法(AuthRequest
AuthRequest authRequest = mock(AuthRequest.class);
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// mock 方法(AuthResponse
AuthUser authUser = randomPojo(AuthUser.class);
AuthResponse<AuthUser> authResponse = new AuthResponse<>(2000, null, authUser);
when(authRequest.login(argThat(authCallback -> {
assertEquals(code, authCallback.getCode());
assertEquals(state, authCallback.getState());
return true;
}))).thenReturn(authResponse);
// 调用
AuthUser result = socialClientService.getAuthUser(socialType, userType, code, state);
// 断言
assertSame(authUser, result);
}
@Test
public void testAuthSocialUser_fail() {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String code = randomString();
String state = randomString();
// mock 方法(AuthRequest
AuthRequest authRequest = mock(AuthRequest.class);
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// mock 方法(AuthResponse
AuthResponse<AuthUser> authResponse = new AuthResponse<>(0, "模拟失败", null);
when(authRequest.login(argThat(authCallback -> {
assertEquals(code, authCallback.getCode());
assertEquals(state, authCallback.getState());
return true;
}))).thenReturn(authResponse);
// 调用并断言
assertServiceException(
() -> socialClientService.getAuthUser(socialType, userType, code, state),
SOCIAL_USER_AUTH_FAILURE, "模拟失败");
}
@Test
public void testBuildAuthRequest_clientNull() {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(SocialTypeEnum.class).getType();
// mock 获得对应的 AuthRequest 实现
AuthRequest authRequest = mock(AuthDefaultRequest.class);
AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// 调用
AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
// 断言
assertSame(authRequest, result);
assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
}
@Test
public void testBuildAuthRequest_clientDisable() {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(SocialTypeEnum.class).getType();
// mock 获得对应的 AuthRequest 实现
AuthRequest authRequest = mock(AuthDefaultRequest.class);
AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(authRequest, "config");
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
.setUserType(userType).setSocialType(socialType));
socialClientMapper.insert(client);
// 调用
AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
// 断言
assertSame(authRequest, result);
assertSame(authConfig, ReflectUtil.getFieldValue(authConfig, "config"));
}
@Test
public void testBuildAuthRequest_clientEnable() {
// 准备参数
Integer socialType = SocialTypeEnum.WECHAT_MP.getType();
Integer userType = randomPojo(SocialTypeEnum.class).getType();
// mock 获得对应的 AuthRequest 实现
AuthConfig authConfig = mock(AuthConfig.class);
AuthRequest authRequest = mock(AuthDefaultRequest.class);
ReflectUtil.setFieldValue(authRequest, "config", authConfig);
when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setUserType(userType).setSocialType(socialType));
socialClientMapper.insert(client);
// 调用
AuthRequest result = socialClientService.buildAuthRequest(socialType, userType);
// 断言
assertSame(authRequest, result);
assertNotSame(authConfig, ReflectUtil.getFieldValue(authRequest, "config"));
}
// =================== 微信公众号独有 ===================
@Test
public void testCreateWxMpJsapiSignature() throws WxErrorException {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String url = randomString();
// mock 方法
WxJsapiSignature signature = randomPojo(WxJsapiSignature.class);
when(wxMpService.createJsapiSignature(eq(url))).thenReturn(signature);
// 调用
WxJsapiSignature result = socialClientService.createWxMpJsapiSignature(userType, url);
// 断言
assertSame(signature, result);
}
@Test
public void testGetWxMpService_clientNull() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 方法
// 调用
WxMpService result = socialClientService.getWxMpService(userType);
// 断言
assertSame(wxMpService, result);
}
@Test
public void testGetWxMpService_clientDisable() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
.setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
socialClientMapper.insert(client);
// 调用
WxMpService result = socialClientService.getWxMpService(userType);
// 断言
assertSame(wxMpService, result);
}
@Test
public void testGetWxMpService_clientEnable() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MP.getType()));
socialClientMapper.insert(client);
// mock 方法
WxMpProperties.ConfigStorage configStorage = mock(WxMpProperties.ConfigStorage.class);
when(wxMpProperties.getConfigStorage()).thenReturn(configStorage);
// 调用
WxMpService result = socialClientService.getWxMpService(userType);
// 断言
assertNotSame(wxMpService, result);
assertEquals(client.getClientId(), result.getWxMpConfigStorage().getAppId());
assertEquals(client.getClientSecret(), result.getWxMpConfigStorage().getSecret());
}
// =================== 微信小程序独有 ===================
@Test
public void testGetWxMaPhoneNumberInfo_success() throws WxErrorException {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String phoneCode = randomString();
// mock 方法
WxMaUserService userService = mock(WxMaUserService.class);
when(wxMaService.getUserService()).thenReturn(userService);
WxMaPhoneNumberInfo phoneNumber = randomPojo(WxMaPhoneNumberInfo.class);
when(userService.getPhoneNoInfo(eq(phoneCode))).thenReturn(phoneNumber);
// 调用
WxMaPhoneNumberInfo result = socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode);
// 断言
assertSame(phoneNumber, result);
}
@Test
public void testGetWxMaPhoneNumberInfo_exception() throws WxErrorException {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
String phoneCode = randomString();
// mock 方法
WxMaUserService userService = mock(WxMaUserService.class);
when(wxMaService.getUserService()).thenReturn(userService);
WxErrorException wxErrorException = randomPojo(WxErrorException.class);
when(userService.getPhoneNoInfo(eq(phoneCode))).thenThrow(wxErrorException);
// 调用并断言异常
assertServiceException(() -> socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode),
SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR);
}
@Test
public void testGetWxMaService_clientNull() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 方法
// 调用
WxMaService result = socialClientService.getWxMaService(userType);
// 断言
assertSame(wxMaService, result);
}
@Test
public void testGetWxMaService_clientDisable() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())
.setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
socialClientMapper.insert(client);
// 调用
WxMaService result = socialClientService.getWxMaService(userType);
// 断言
assertSame(wxMaService, result);
}
@Test
public void testGetWxMaService_clientEnable() {
// 准备参数
Integer userType = randomPojo(UserTypeEnum.class).getValue();
// mock 数据
SocialClientDO client = randomPojo(SocialClientDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setUserType(userType).setSocialType(SocialTypeEnum.WECHAT_MINI_APP.getType()));
socialClientMapper.insert(client);
// mock 方法
WxMaProperties.ConfigStorage configStorage = mock(WxMaProperties.ConfigStorage.class);
when(wxMaProperties.getConfigStorage()).thenReturn(configStorage);
// 调用
WxMaService result = socialClientService.getWxMaService(userType);
// 断言
assertNotSame(wxMaService, result);
assertEquals(client.getClientId(), result.getWxMaConfig().getAppid());
assertEquals(client.getClientSecret(), result.getWxMaConfig().getSecret());
}
// =================== 客户端管理 ===================
@Test
public void testCreateSocialClient_success() {
// 准备参数
SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class,
o -> o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
.setUserType(randomEle(UserTypeEnum.values()).getValue())
.setStatus(randomCommonStatus()))
.setId(null); // 防止 id 被赋值
// 调用
Long socialClientId = socialClientService.createSocialClient(reqVO);
// 断言
assertNotNull(socialClientId);
// 校验记录的属性是否正确
SocialClientDO socialClient = socialClientMapper.selectById(socialClientId);
assertPojoEquals(reqVO, socialClient, "id");
}
@Test
public void testUpdateSocialClient_success() {
// mock 数据
SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
// 准备参数
SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class, o -> {
o.setId(dbSocialClient.getId()); // 设置更新的 ID
o.setSocialType(randomEle(SocialTypeEnum.values()).getType())
.setUserType(randomEle(UserTypeEnum.values()).getValue())
.setStatus(randomCommonStatus());
});
// 调用
socialClientService.updateSocialClient(reqVO);
// 校验是否更新正确
SocialClientDO socialClient = socialClientMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, socialClient);
}
@Test
public void testUpdateSocialClient_notExists() {
// 准备参数
SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> socialClientService.updateSocialClient(reqVO), SOCIAL_CLIENT_NOT_EXISTS);
}
@Test
public void testDeleteSocialClient_success() {
// mock 数据
SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSocialClient.getId();
// 调用
socialClientService.deleteSocialClient(id);
// 校验数据不存在了
assertNull(socialClientMapper.selectById(id));
}
@Test
public void testDeleteSocialClient_notExists() {
// 准备参数
Long id = randomLongId();
// 调用, 并断言异常
assertServiceException(() -> socialClientService.deleteSocialClient(id), SOCIAL_CLIENT_NOT_EXISTS);
}
@Test
public void testGetSocialClient() {
// mock 数据
SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class);
socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSocialClient.getId();
// 调用
SocialClientDO socialClient = socialClientService.getSocialClient(id);
// 校验数据正确
assertPojoEquals(dbSocialClient, socialClient);
}
@Test
public void testGetSocialClientPage() {
// mock 数据
SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class, o -> { // 等会查询到
o.setName("芋头");
o.setSocialType(SocialTypeEnum.GITEE.getType());
o.setUserType(UserTypeEnum.ADMIN.getValue());
o.setClientId("chenfeng");
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
});
socialClientMapper.insert(dbSocialClient);
// 测试 name 不匹配
socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setName(randomString())));
// 测试 socialType 不匹配
socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setSocialType(SocialTypeEnum.DINGTALK.getType())));
// 测试 userType 不匹配
socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
// 测试 clientId 不匹配
socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientId("dao")));
// 测试 status 不匹配
socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 准备参数
SocialClientPageReqVO reqVO = new SocialClientPageReqVO();
reqVO.setName("");
reqVO.setSocialType(SocialTypeEnum.GITEE.getType());
reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
reqVO.setClientId("yu");
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
// 调用
PageResult<SocialClientDO> pageResult = socialClientService.getSocialClientPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbSocialClient, pageResult.getList().get(0));
}
}
@@ -1,288 +0,0 @@
package com.cf.imes.module.system.service.social;
import com.cf.imes.framework.common.enums.UserTypeEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.test.core.ut.BaseDbUnitTest;
import com.cf.imes.module.system.api.social.dto.SocialUserBindReqDTO;
import com.cf.imes.module.system.api.social.dto.SocialUserRespDTO;
import com.cf.imes.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
import com.cf.imes.module.system.dal.dataobject.social.SocialUserBindDO;
import com.cf.imes.module.system.dal.dataobject.social.SocialUserDO;
import com.cf.imes.module.system.dal.mysql.social.SocialUserBindMapper;
import com.cf.imes.module.system.dal.mysql.social.SocialUserMapper;
import com.cf.imes.module.system.enums.social.SocialTypeEnum;
import me.zhyd.oauth.model.AuthUser;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import java.util.List;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.hutool.core.util.RandomUtil.randomLong;
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.buildTime;
import static com.cf.imes.framework.common.util.json.JsonUtils.toJsonString;
import static com.cf.imes.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals;
import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceException;
import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo;
import static com.cf.imes.framework.test.core.util.RandomUtils.randomString;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.when;
/**
* {@link SocialUserServiceImpl} 的单元测试类
*
* @author 晨丰科技
*/
@Import(SocialUserServiceImpl.class)
public class SocialUserServiceImplTest extends BaseDbUnitTest {
@Resource
private SocialUserServiceImpl socialUserService;
@Resource
private SocialUserMapper socialUserMapper;
@Resource
private SocialUserBindMapper socialUserBindMapper;
@MockBean
private SocialClientService socialClientService;
@Test
public void testGetSocialUserList() {
Long userId = 1L;
Integer userType = UserTypeEnum.ADMIN.getValue();
// mock 获得社交用户
SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(SocialTypeEnum.GITEE.getType());
socialUserMapper.insert(socialUser); // 可被查到
socialUserMapper.insert(randomPojo(SocialUserDO.class)); // 不可被查到
// mock 获得绑定
socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class) // 可被查询到
.setUserId(userId).setUserType(userType).setSocialType(SocialTypeEnum.GITEE.getType())
.setSocialUserId(socialUser.getId()));
socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class) // 不可被查询到
.setUserId(2L).setUserType(userType).setSocialType(SocialTypeEnum.DINGTALK.getType()));
// 调用
List<SocialUserDO> result = socialUserService.getSocialUserList(userId, userType);
// 断言
assertEquals(1, result.size());
assertPojoEquals(socialUser, result.get(0));
}
@Test
public void testBindSocialUser() {
// 准备参数
SocialUserBindReqDTO reqDTO = new SocialUserBindReqDTO()
.setUserId(1L).setUserType(UserTypeEnum.ADMIN.getValue())
.setSocialType(SocialTypeEnum.GITEE.getType()).setCode("test_code").setState("test_state");
// mock 数据:获得社交用户
SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(reqDTO.getSocialType())
.setCode(reqDTO.getCode()).setState(reqDTO.getState());
socialUserMapper.insert(socialUser);
// mock 数据:用户可能之前已经绑定过该社交类型
socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class).setUserId(1L).setUserType(UserTypeEnum.ADMIN.getValue())
.setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(-1L));
// mock 数据:社交用户可能之前绑定过别的用户
socialUserBindMapper.insert(randomPojo(SocialUserBindDO.class).setUserType(UserTypeEnum.ADMIN.getValue())
.setSocialType(SocialTypeEnum.GITEE.getType()).setSocialUserId(socialUser.getId()));
// 调用
String openid = socialUserService.bindSocialUser(reqDTO);
// 断言
List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectList();
assertEquals(1, socialUserBinds.size());
assertEquals(socialUser.getOpenid(), openid);
}
@Test
public void testUnbindSocialUser_success() {
// 准备参数
Long userId = 1L;
Integer userType = UserTypeEnum.ADMIN.getValue();
Integer type = SocialTypeEnum.GITEE.getType();
String openid = "test_openid";
// mock 数据:社交用户
SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(type).setOpenid(openid);
socialUserMapper.insert(socialUser);
// mock 数据:社交绑定关系
SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType)
.setUserId(userId).setSocialType(type);
socialUserBindMapper.insert(socialUserBind);
// 调用
socialUserService.unbindSocialUser(userId, userType, type, openid);
// 断言
assertEquals(0, socialUserBindMapper.selectCount(null).intValue());
}
@Test
public void testUnbindSocialUser_notFound() {
// 调用,并断言
assertServiceException(
() -> socialUserService.unbindSocialUser(randomLong(), UserTypeEnum.ADMIN.getValue(),
SocialTypeEnum.GITEE.getType(), "test_openid"),
SOCIAL_USER_NOT_FOUND);
}
@Test
public void testGetSocialUser() {
// 准备参数
Integer userType = UserTypeEnum.ADMIN.getValue();
Integer type = SocialTypeEnum.GITEE.getType();
String code = "tudou";
String state = "yuanma";
// mock 社交用户
SocialUserDO socialUserDO = randomPojo(SocialUserDO.class).setType(type).setCode(code).setState(state);
socialUserMapper.insert(socialUserDO);
// mock 社交用户的绑定
Long userId = randomLong();
SocialUserBindDO socialUserBind = randomPojo(SocialUserBindDO.class).setUserType(userType).setUserId(userId)
.setSocialType(type).setSocialUserId(socialUserDO.getId());
socialUserBindMapper.insert(socialUserBind);
// 调用
SocialUserRespDTO socialUser = socialUserService.getSocialUserByCode(userType, type, code, state);
// 断言
assertEquals(userId, socialUser.getUserId());
assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid());
}
@Test
public void testAuthSocialUser_exists() {
// 准备参数
Integer socialType = SocialTypeEnum.GITEE.getType();
Integer userType = randomEle(SocialTypeEnum.values()).getType();
String code = "tudou";
String state = "yuanma";
// mock 方法
SocialUserDO socialUser = randomPojo(SocialUserDO.class).setType(socialType).setCode(code).setState(state);
socialUserMapper.insert(socialUser);
// 调用
SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
// 断言
assertPojoEquals(socialUser, result);
}
@Test
public void testAuthSocialUser_notNull() {
// mock 数据
SocialUserDO socialUser = randomPojo(SocialUserDO.class,
o -> o.setType(SocialTypeEnum.GITEE.getType()).setCode("tudou").setState("yuanma"));
socialUserMapper.insert(socialUser);
// 准备参数
Integer socialType = SocialTypeEnum.GITEE.getType();
Integer userType = randomEle(SocialTypeEnum.values()).getType();
String code = "tudou";
String state = "yuanma";
// 调用
SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
// 断言
assertPojoEquals(socialUser, result);
}
@Test
public void testAuthSocialUser_insert() {
// 准备参数
Integer socialType = SocialTypeEnum.GITEE.getType();
Integer userType = randomEle(SocialTypeEnum.values()).getType();
String code = "tudou";
String state = "yuanma";
// mock 方法
AuthUser authUser = randomPojo(AuthUser.class);
when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
// 调用
SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
// 断言
assertBindSocialUser(socialType, result, authUser);
assertEquals(code, result.getCode());
assertEquals(state, result.getState());
}
@Test
public void testAuthSocialUser_update() {
// 准备参数
Integer socialType = SocialTypeEnum.GITEE.getType();
Integer userType = randomEle(SocialTypeEnum.values()).getType();
String code = "tudou";
String state = "yuanma";
// mock 数据
socialUserMapper.insert(randomPojo(SocialUserDO.class).setType(socialType).setOpenid("test_openid"));
// mock 方法
AuthUser authUser = randomPojo(AuthUser.class);
when(socialClientService.getAuthUser(eq(socialType), eq(userType), eq(code), eq(state))).thenReturn(authUser);
// 调用
SocialUserDO result = socialUserService.authSocialUser(socialType, userType, code, state);
// 断言
assertBindSocialUser(socialType, result, authUser);
assertEquals(code, result.getCode());
assertEquals(state, result.getState());
}
private void assertBindSocialUser(Integer type, SocialUserDO socialUser, AuthUser authUser) {
assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());
assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());
assertEquals(authUser.getNickname(), socialUser.getNickname());
assertEquals(authUser.getAvatar(), socialUser.getAvatar());
assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());
assertEquals(type, socialUser.getType());
assertEquals(authUser.getUuid(), socialUser.getOpenid());
}
@Test
public void testGetSocialUser_id() {
// mock 数据
SocialUserDO socialUserDO = randomPojo(SocialUserDO.class);
socialUserMapper.insert(socialUserDO);
// 参数准备
Long id = socialUserDO.getId();
// 调用
SocialUserDO dbSocialUserDO = socialUserService.getSocialUser(id);
// 断言
assertPojoEquals(socialUserDO, dbSocialUserDO);
}
@Test
public void testGetSocialUserPage() {
// mock 数据
SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, o -> { // 等会查询到
o.setType(SocialTypeEnum.GITEE.getType());
o.setNickname("晨丰");
o.setOpenid("chenfengyuanma");
o.setCreateTime(buildTime(2020, 1, 15));
});
socialUserMapper.insert(dbSocialUser);
// 测试 type 不匹配
socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setType(SocialTypeEnum.DINGTALK.getType())));
// 测试 nickname 不匹配
socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setNickname(randomString())));
// 测试 openid 不匹配
socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setOpenid("java")));
// 测试 createTime 不匹配
socialUserMapper.insert(cloneIgnoreId(dbSocialUser, o -> o.setCreateTime(buildTime(2020, 1, 21))));
// 准备参数
SocialUserPageReqVO reqVO = new SocialUserPageReqVO();
reqVO.setType(SocialTypeEnum.GITEE.getType());
reqVO.setNickname("");
reqVO.setOpenid("chenfeng");
reqVO.setCreateTime(buildBetweenTime(2020, 1, 10, 2020, 1, 20));
// 调用
PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbSocialUser, pageResult.getList().get(0));
}
}
@@ -23,7 +23,6 @@ import com.cf.imes.module.system.dal.mysql.dept.UserPostMapper;
import com.cf.imes.module.system.dal.mysql.user.AdminUserMapper;
import com.cf.imes.module.system.enums.common.SexEnum;
import com.cf.imes.module.system.service.dept.DeptService;
import com.cf.imes.module.system.service.dept.PostService;
import com.cf.imes.module.system.service.permission.PermissionService;
import com.cf.imes.module.system.service.organ.OrganService;
import org.junit.jupiter.api.Test;
@@ -69,8 +68,6 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
@MockBean
private DeptService deptService;
@MockBean
private PostService postService;
@MockBean
private PermissionService permissionService;
@MockBean
private PasswordEncoder passwordEncoder;
@@ -419,7 +416,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest {
UserImportExcelVO importUser = randomPojo(UserImportExcelVO.class, o -> {
});
// mock 方法,模拟失败
doThrow(new ServiceException(DEPT_NOT_FOUND)).when(deptService).validateDeptList(any());
doThrow(new ServiceException(DEPT_NOT_FOUND)).when(deptService).validDept(any());
// 调用
UserImportRespVO respVO = userService.importUserList(newArrayList(importUser), true, 1L);
@@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS "system_dept" (
"name" varchar(30) NOT NULL DEFAULT '',
"parent_id" bigint NOT NULL DEFAULT '0',
"sort" int NOT NULL DEFAULT '0',
"leader_user_id" bigint DEFAULT NULL,
"leader" varchar(30) DEFAULT NULL,
"phone" varchar(11) DEFAULT NULL,
"email" varchar(50) DEFAULT NULL,
"status" tinyint NOT NULL,
@@ -12,7 +12,7 @@ CREATE TABLE IF NOT EXISTS "system_dept" (
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
"organ_id" bigint not null default '0',
PRIMARY KEY ("id")
) COMMENT '部门表';
@@ -405,7 +405,7 @@ CREATE TABLE IF NOT EXISTS "system_social_user_bind" (
PRIMARY KEY ("id")
) COMMENT '社交用户的绑定';
CREATE TABLE IF NOT EXISTS "system_tenant" (
CREATE TABLE IF NOT EXISTS "system_organization" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(63) NOT NULL,
"contact_user_id" bigint NOT NULL DEFAULT '0',