Commit 984113e6d93c2eeeae10f45a99ca3050f45698f5

Authored by budliang
2 parents ccba513f 252a2678

Merge branch 'rouyi/master' into feature/notice_test

# Conflicts:
#	src/test/resources/sql/create_tables.sql
src/main/java/cn/iocoder/dashboard/framework/mybatis/core/handler/DefaultDBFieldHandler.java
@@ -57,7 +57,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { @@ -57,7 +57,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
57 } 57 }
58 // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 58 // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
59 if (Objects.nonNull(loginUser) && Objects.isNull(modifier)) { 59 if (Objects.nonNull(loginUser) && Objects.isNull(modifier)) {
60 - setFieldValByName("updater", loginUser.getId(), metaObject); 60 + setFieldValByName("updater", loginUser.getId().toString(), metaObject);
61 } 61 }
62 } 62 }
63 } 63 }
src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/dept/SysDeptBaseVO.java
@@ -25,7 +25,7 @@ public class SysDeptBaseVO { @@ -25,7 +25,7 @@ public class SysDeptBaseVO {
25 private Long parentId; 25 private Long parentId;
26 26
27 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") 27 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
28 - @NotBlank(message = "显示顺序不能为空") 28 + @NotNull(message = "显示顺序不能为空")
29 private Integer sort; 29 private Integer sort;
30 30
31 @ApiModelProperty(value = "负责人", example = "芋道") 31 @ApiModelProperty(value = "负责人", example = "芋道")
src/main/java/cn/iocoder/dashboard/modules/system/controller/dept/vo/post/SysPostBaseVO.java
@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 import javax.validation.constraints.NotBlank; 6 import javax.validation.constraints.NotBlank;
  7 +import javax.validation.constraints.NotNull;
7 import javax.validation.constraints.Size; 8 import javax.validation.constraints.Size;
8 9
9 /** 10 /**
@@ -24,7 +25,7 @@ public class SysPostBaseVO { @@ -24,7 +25,7 @@ public class SysPostBaseVO {
24 private String code; 25 private String code;
25 26
26 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") 27 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
27 - @NotBlank(message = "显示顺序不能为空") 28 + @NotNull(message = "显示顺序不能为空")
28 private Integer sort; 29 private Integer sort;
29 30
30 @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类") 31 @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
src/main/java/cn/iocoder/dashboard/modules/system/controller/dict/vo/data/SysDictDataBaseVO.java
@@ -15,7 +15,7 @@ import javax.validation.constraints.Size; @@ -15,7 +15,7 @@ import javax.validation.constraints.Size;
15 public class SysDictDataBaseVO { 15 public class SysDictDataBaseVO {
16 16
17 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") 17 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
18 - @NotBlank(message = "显示顺序不能为空") 18 + @NotNull(message = "显示顺序不能为空")
19 private Integer sort; 19 private Integer sort;
20 20
21 @ApiModelProperty(value = "字典标签", required = true, example = "芋道") 21 @ApiModelProperty(value = "字典标签", required = true, example = "芋道")
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/menu/SysMenuBaseVO.java
@@ -28,7 +28,7 @@ public class SysMenuBaseVO { @@ -28,7 +28,7 @@ public class SysMenuBaseVO {
28 private Integer type; 28 private Integer type;
29 29
30 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") 30 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
31 - @NotBlank(message = "显示顺序不能为空") 31 + @NotNull(message = "显示顺序不能为空")
32 private Integer sort; 32 private Integer sort;
33 33
34 @ApiModelProperty(value = "父菜单 ID", required = true, example = "1024") 34 @ApiModelProperty(value = "父菜单 ID", required = true, example = "1024")
src/main/java/cn/iocoder/dashboard/modules/system/controller/permission/vo/role/SysRoleBaseVO.java
@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
4 import lombok.Data; 4 import lombok.Data;
5 5
6 import javax.validation.constraints.NotBlank; 6 import javax.validation.constraints.NotBlank;
  7 +import javax.validation.constraints.NotNull;
7 import javax.validation.constraints.Size; 8 import javax.validation.constraints.Size;
8 9
9 /** 10 /**
@@ -24,7 +25,7 @@ public class SysRoleBaseVO { @@ -24,7 +25,7 @@ public class SysRoleBaseVO {
24 private String code; 25 private String code;
25 26
26 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024") 27 @ApiModelProperty(value = "显示顺序不能为空", required = true, example = "1024")
27 - @NotBlank(message = "显示顺序不能为空") 28 + @NotNull(message = "显示顺序不能为空")
28 private Integer sort; 29 private Integer sort;
29 30
30 @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "见 SysRoleTypeEnum 枚举") 31 @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "见 SysRoleTypeEnum 枚举")
src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptServiceTest.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.dept;
  2 +
  3 +import cn.iocoder.dashboard.BaseDbUnitTest;
  4 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO;
  6 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptListReqVO;
  7 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO;
  8 +import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO;
  9 +import cn.iocoder.dashboard.modules.system.dal.mysql.dept.SysDeptMapper;
  10 +import cn.iocoder.dashboard.modules.system.enums.dept.DeptIdEnum;
  11 +import cn.iocoder.dashboard.modules.system.mq.producer.dept.SysDeptProducer;
  12 +import cn.iocoder.dashboard.modules.system.service.dept.impl.SysDeptServiceImpl;
  13 +import cn.iocoder.dashboard.util.collection.ArrayUtils;
  14 +import cn.iocoder.dashboard.util.object.ObjectUtils;
  15 +import com.google.common.collect.Multimap;
  16 +import org.junit.jupiter.api.Test;
  17 +import org.springframework.boot.test.mock.mockito.MockBean;
  18 +import org.springframework.context.annotation.Import;
  19 +
  20 +import javax.annotation.Resource;
  21 +import java.util.Date;
  22 +import java.util.List;
  23 +import java.util.Map;
  24 +import java.util.function.Consumer;
  25 +
  26 +import static cn.hutool.core.bean.BeanUtil.getFieldValue;
  27 +import static cn.hutool.core.util.RandomUtil.randomEle;
  28 +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
  29 +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
  30 +import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
  31 +import static cn.iocoder.dashboard.util.RandomUtils.*;
  32 +import static org.junit.jupiter.api.Assertions.*;
  33 +import static org.mockito.Mockito.times;
  34 +import static org.mockito.Mockito.verify;
  35 +
  36 +/**
  37 + * {@link SysDeptServiceImpl} 的单元测试类
  38 + *
  39 + * @author niudehua
  40 + */
  41 +@Import(SysDeptServiceImpl.class)
  42 +class SysDeptServiceTest extends BaseDbUnitTest {
  43 +
  44 + @Resource
  45 + private SysDeptServiceImpl deptService;
  46 + @Resource
  47 + private SysDeptMapper deptMapper;
  48 + @MockBean
  49 + private SysDeptProducer deptProducer;
  50 +
  51 + @Test
  52 + @SuppressWarnings("unchecked")
  53 + void testInitLocalCache() {
  54 + // mock 数据
  55 + SysDeptDO deptDO1 = randomDeptDO();
  56 + deptMapper.insert(deptDO1);
  57 + SysDeptDO deptDO2 = randomDeptDO();
  58 + deptMapper.insert(deptDO2);
  59 +
  60 + // 调用
  61 + deptService.initLocalCache();
  62 + // 断言 deptCache 缓存
  63 + Map<Long, SysDeptDO> deptCache = (Map<Long, SysDeptDO>) getFieldValue(deptService, "deptCache");
  64 + assertEquals(2, deptCache.size());
  65 + assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId()));
  66 + assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId()));
  67 + // 断言 parentDeptCache 缓存
  68 + Multimap<Long, SysDeptDO> parentDeptCache = (Multimap<Long, SysDeptDO>) getFieldValue(deptService, "parentDeptCache");
  69 + assertEquals(2, parentDeptCache.size());
  70 + assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId()));
  71 + assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId()));
  72 + // 断言 maxUpdateTime 缓存
  73 + Date maxUpdateTime = (Date) getFieldValue(deptService, "maxUpdateTime");
  74 + assertEquals(ObjectUtils.max(deptDO1.getUpdateTime(), deptDO2.getUpdateTime()), maxUpdateTime);
  75 +
  76 + }
  77 +
  78 + @Test
  79 + void testListDepts() {
  80 + // mock 数据
  81 + SysDeptDO dept = randomPojo(SysDeptDO.class, o -> { // 等会查询到
  82 + o.setName("开发部");
  83 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  84 + });
  85 + deptMapper.insert(dept);
  86 + // 测试 name 不匹配
  87 + deptMapper.insert(ObjectUtils.clone(dept, o -> o.setName("发")));
  88 + // 测试 status 不匹配
  89 + deptMapper.insert(ObjectUtils.clone(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  90 + // 准备参数
  91 + SysDeptListReqVO reqVO = new SysDeptListReqVO();
  92 + reqVO.setName("开");
  93 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  94 + // 调用
  95 + List<SysDeptDO> sysDeptDOS = deptService.listDepts(reqVO);
  96 + // 断言
  97 + assertEquals(1, sysDeptDOS.size());
  98 + assertPojoEquals(dept, sysDeptDOS.get(0));
  99 + }
  100 +
  101 + @Test
  102 + void testCreateDept_success() {
  103 + // 准备参数
  104 + SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class,
  105 + o -> {
  106 + o.setParentId(DeptIdEnum.ROOT.getId());
  107 + o.setStatus(randomCommonStatus());
  108 + });
  109 + // 调用
  110 + Long deptId = deptService.createDept(reqVO);
  111 + // 断言
  112 + assertNotNull(deptId);
  113 + // 校验记录的属性是否正确
  114 + SysDeptDO deptDO = deptMapper.selectById(deptId);
  115 + assertPojoEquals(reqVO, deptDO);
  116 + // 校验调用
  117 + verify(deptProducer, times(1)).sendDeptRefreshMessage();
  118 + }
  119 +
  120 + @Test
  121 + void testUpdateDept_success() {
  122 + // mock 数据
  123 + SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus()));
  124 + deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
  125 + // 准备参数
  126 + SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class, o -> {
  127 + // 设置更新的 ID
  128 + o.setParentId(DeptIdEnum.ROOT.getId());
  129 + o.setId(dbDeptDO.getId());
  130 + o.setStatus(randomCommonStatus());
  131 + });
  132 + // 调用
  133 + deptService.updateDept(reqVO);
  134 + // 校验是否更新正确
  135 + SysDeptDO deptDO = deptMapper.selectById(reqVO.getId()); // 获取最新的
  136 + assertPojoEquals(reqVO, deptDO);
  137 + }
  138 +
  139 + @Test
  140 + void testDeleteDept_success() {
  141 + // mock 数据
  142 + SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus()));
  143 + deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据
  144 + // 准备参数
  145 + Long id = dbDeptDO.getId();
  146 + // 调用
  147 + deptService.deleteDept(id);
  148 + // 校验数据不存在了
  149 + assertNull(deptMapper.selectById(id));
  150 + }
  151 +
  152 + @Test
  153 + void testCheckDept_nameDuplicateForUpdate() {
  154 + // mock 数据
  155 + SysDeptDO deptDO = randomDeptDO();
  156 + // 设置根节点部门
  157 + deptDO.setParentId(DeptIdEnum.ROOT.getId());
  158 + deptMapper.insert(deptDO);
  159 + // mock 数据 稍后模拟重复它的 name
  160 + SysDeptDO nameDeptDO = randomDeptDO();
  161 + // 设置根节点部门
  162 + nameDeptDO.setParentId(DeptIdEnum.ROOT.getId());
  163 + deptMapper.insert(nameDeptDO);
  164 + // 准备参数
  165 + SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class,
  166 + o -> {
  167 + // 设置根节点部门
  168 + o.setParentId(DeptIdEnum.ROOT.getId());
  169 + // 设置更新的 ID
  170 + o.setId(deptDO.getId());
  171 + // 模拟 name 重复
  172 + o.setName(nameDeptDO.getName());
  173 + });
  174 + // 调用, 并断言异常
  175 + assertServiceException(() -> deptService.updateDept(reqVO), DEPT_NAME_DUPLICATE);
  176 +
  177 + }
  178 +
  179 + @Test
  180 + void testCheckDept_parentNotExitsForCreate() {
  181 + SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class,
  182 + o -> o.setStatus(randomCommonStatus()));
  183 + // 调用,并断言异常
  184 + assertServiceException(() -> deptService.createDept(reqVO), DEPT_PARENT_NOT_EXITS);
  185 + }
  186 +
  187 + @Test
  188 + void testCheckDept_notFoundForDelete() {
  189 + // 准备参数
  190 + Long id = randomLongId();
  191 + // 调用, 并断言异常
  192 + assertServiceException(() -> deptService.deleteDept(id), DEPT_NOT_FOUND);
  193 + }
  194 +
  195 + @Test
  196 + void testCheckDept_exitsChildrenForDelete() {
  197 + // mock 数据
  198 + SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus()));
  199 + deptMapper.insert(parentDept);// @Sql: 先插入出一条存在的数据
  200 + // 准备参数
  201 + SysDeptDO childrenDeptDO = randomPojo(SysDeptDO.class, o -> {
  202 + o.setParentId(parentDept.getId());
  203 + o.setStatus(randomCommonStatus());
  204 + });
  205 + // 插入子部门
  206 + deptMapper.insert(childrenDeptDO);
  207 + // 调用, 并断言异常
  208 + assertServiceException(() -> deptService.deleteDept(parentDept.getId()), DEPT_EXITS_CHILDREN);
  209 + }
  210 +
  211 + @Test
  212 + void testCheckDept_parentErrorForUpdate() {
  213 + // mock 数据
  214 + SysDeptDO dbDeptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(randomCommonStatus()));
  215 + deptMapper.insert(dbDeptDO);
  216 + // 准备参数
  217 + SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class,
  218 + o -> {
  219 + // 设置自己为父部门
  220 + o.setParentId(dbDeptDO.getId());
  221 + // 设置更新的 ID
  222 + o.setId(dbDeptDO.getId());
  223 + });
  224 + // 调用, 并断言异常
  225 + assertServiceException(() -> deptService.updateDept(reqVO), DEPT_PARENT_ERROR);
  226 + }
  227 +
  228 + @Test
  229 + void testCheckDept_notEnableForCreate() {
  230 + // mock 数据
  231 + SysDeptDO deptDO = randomPojo(SysDeptDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
  232 + deptMapper.insert(deptDO);
  233 + // 准备参数
  234 + SysDeptCreateReqVO reqVO = randomPojo(SysDeptCreateReqVO.class,
  235 + o -> {
  236 + // 设置未启用的部门为副部门
  237 + o.setParentId(deptDO.getId());
  238 + });
  239 + // 调用, 并断言异常
  240 + assertServiceException(() -> deptService.createDept(reqVO), DEPT_NOT_ENABLE);
  241 + }
  242 +
  243 + @Test
  244 + void testCheckDept_parentIsChildForUpdate() {
  245 + // mock 数据
  246 + SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
  247 + deptMapper.insert(parentDept);
  248 + SysDeptDO childDept = randomPojo(SysDeptDO.class, o -> {
  249 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  250 + o.setParentId(parentDept.getId());
  251 + });
  252 + deptMapper.insert(childDept);
  253 + // 初始化本地缓存
  254 + deptService.initLocalCache();
  255 + // 准备参数
  256 + SysDeptUpdateReqVO reqVO = randomPojo(SysDeptUpdateReqVO.class,
  257 + o -> {
  258 + // 设置自己的子部门为父部门
  259 + o.setParentId(childDept.getId());
  260 + // 设置更新的 ID
  261 + o.setId(parentDept.getId());
  262 + });
  263 + // 调用, 并断言异常
  264 + assertServiceException(() -> deptService.updateDept(reqVO), DEPT_PARENT_IS_CHILD);
  265 + }
  266 +
  267 + @SafeVarargs
  268 + private static SysDeptDO randomDeptDO(Consumer<SysDeptDO>... consumers) {
  269 + Consumer<SysDeptDO> consumer = (o) -> {
  270 + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
  271 + };
  272 + return randomPojo(SysDeptDO.class, ArrayUtils.append(consumer, consumers));
  273 + }
  274 +}
src/test/java/cn/iocoder/dashboard/modules/system/service/dept/SysPostServiceTest.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.service.dept;
  2 +
  3 +import cn.iocoder.dashboard.BaseDbUnitTest;
  4 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.dashboard.common.pojo.PageResult;
  6 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostCreateReqVO;
  7 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostExportReqVO;
  8 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostPageReqVO;
  9 +import cn.iocoder.dashboard.modules.system.controller.dept.vo.post.SysPostUpdateReqVO;
  10 +import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO;
  11 +import cn.iocoder.dashboard.modules.system.dal.mysql.dept.SysPostMapper;
  12 +import cn.iocoder.dashboard.modules.system.service.dept.impl.SysPostServiceImpl;
  13 +import cn.iocoder.dashboard.util.collection.ArrayUtils;
  14 +import cn.iocoder.dashboard.util.object.ObjectUtils;
  15 +import org.junit.jupiter.api.Test;
  16 +import org.springframework.context.annotation.Import;
  17 +
  18 +import javax.annotation.Resource;
  19 +import java.util.List;
  20 +import java.util.function.Consumer;
  21 +
  22 +import static cn.hutool.core.util.RandomUtil.randomEle;
  23 +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
  24 +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
  25 +import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
  26 +import static cn.iocoder.dashboard.util.RandomUtils.randomLongId;
  27 +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
  28 +import static org.junit.jupiter.api.Assertions.*;
  29 +
  30 +/**
  31 + * {@link SysPostServiceImpl} 的单元测试类
  32 + *
  33 + * @author niudehua
  34 + */
  35 +@Import(SysPostServiceImpl.class)
  36 +class SysPostServiceTest extends BaseDbUnitTest {
  37 +
  38 + @Resource
  39 + private SysPostServiceImpl postService;
  40 + @Resource
  41 + private SysPostMapper postMapper;
  42 +
  43 + @Test
  44 + void testPagePosts() {
  45 + // mock 数据
  46 + SysPostDO postDO = randomPojo(SysPostDO.class, o -> {
  47 + o.setName("码仔");
  48 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  49 + });
  50 + postMapper.insert(postDO);
  51 + // 测试 name 不匹配
  52 + postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
  53 + // 测试 status 不匹配
  54 + postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  55 +
  56 + // 准备参数
  57 + SysPostPageReqVO reqVO = new SysPostPageReqVO();
  58 + reqVO.setName("码");
  59 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  60 +
  61 + // 调用
  62 + PageResult<SysPostDO> pageResult = postService.pagePosts(reqVO);
  63 +
  64 + // 断言
  65 + assertEquals(1, pageResult.getTotal());
  66 + assertEquals(1, pageResult.getList().size());
  67 + assertPojoEquals(postDO, pageResult.getList().get(0));
  68 + }
  69 +
  70 + @Test
  71 + void testListPosts() {
  72 + // mock 数据
  73 + SysPostDO postDO = randomPojo(SysPostDO.class, o -> {
  74 + o.setName("码仔");
  75 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  76 + });
  77 + postMapper.insert(postDO);
  78 + // 测试 name 不匹配
  79 + postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
  80 + // 测试 status 不匹配
  81 + postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  82 + // 准备参数
  83 + SysPostExportReqVO reqVO = new SysPostExportReqVO();
  84 + reqVO.setName("码");
  85 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  86 +
  87 + // 调用
  88 + List<SysPostDO> list = postService.listPosts(reqVO);
  89 + // 断言
  90 + assertEquals(1, list.size());
  91 + assertPojoEquals(postDO, list.get(0));
  92 + }
  93 +
  94 + @Test
  95 + void testGetPost() {
  96 + // mock 数据
  97 + SysPostDO dbPostDO = randomPostDO();
  98 + postMapper.insert(dbPostDO);
  99 + // 准备参数
  100 + Long id = dbPostDO.getId();
  101 + // 调用
  102 + SysPostDO post = postService.getPost(id);
  103 + // 断言
  104 + assertNotNull(post);
  105 + assertPojoEquals(dbPostDO, post);
  106 + }
  107 +
  108 + @Test
  109 + void testCreatePost_success() {
  110 + // 准备参数
  111 + SysPostCreateReqVO reqVO = randomPojo(SysPostCreateReqVO.class,
  112 + o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()));
  113 + // 调用
  114 + Long postId = postService.createPost(reqVO);
  115 + // 断言
  116 + assertNotNull(postId);
  117 + // 校验记录的属性是否正确
  118 + SysPostDO post = postMapper.selectById(postId);
  119 + assertPojoEquals(reqVO, post);
  120 + }
  121 +
  122 + @Test
  123 + void testUpdatePost_success() {
  124 + // mock 数据
  125 + SysPostDO postDO = randomPostDO();
  126 + postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
  127 + // 准备参数
  128 + SysPostUpdateReqVO reqVO = randomPojo(SysPostUpdateReqVO.class,
  129 + o -> {
  130 + // 设置更新的 ID
  131 + o.setId(postDO.getId());
  132 + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus());
  133 + });
  134 + // 调用
  135 + postService.updatePost(reqVO);
  136 + // 校验是否更新正确
  137 + SysPostDO post = postMapper.selectById(reqVO.getId());// 获取最新的
  138 + assertPojoEquals(reqVO, post);
  139 + }
  140 +
  141 + @Test
  142 + void testDeletePost_success() {
  143 + // mock 数据
  144 + SysPostDO postDO = randomPostDO();
  145 + postMapper.insert(postDO);
  146 + // 准备参数
  147 + Long id = postDO.getId();
  148 + // 调用
  149 + postService.deletePost(id);
  150 + assertNull(postMapper.selectById(id));
  151 + }
  152 +
  153 + @Test
  154 + void testCheckPost_notFoundForDelete() {
  155 + // 准备参数
  156 + Long id = randomLongId();
  157 + // 调用, 并断言异常
  158 + assertServiceException(() -> postService.deletePost(id), POST_NOT_FOUND);
  159 + }
  160 +
  161 + @Test
  162 + void testCheckPost_nameDuplicateForCreate() {
  163 + // mock 数据
  164 + SysPostDO postDO = randomPostDO();
  165 + postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据
  166 + // 准备参数
  167 + SysPostCreateReqVO reqVO = randomPojo(SysPostCreateReqVO.class,
  168 + // 模拟 name 重复
  169 + o -> o.setName(postDO.getName()));
  170 + assertServiceException(() -> postService.createPost(reqVO), POST_NAME_DUPLICATE);
  171 + }
  172 +
  173 + @Test
  174 + void testCheckPost_codeDuplicateForUpdate() {
  175 + // mock 数据
  176 + SysPostDO postDO = randomPostDO();
  177 + postMapper.insert(postDO);
  178 + // mock 数据 稍后模拟重复它的 code
  179 + SysPostDO codePostDO = randomPostDO();
  180 + postMapper.insert(codePostDO);
  181 + // 准备参数
  182 + SysPostUpdateReqVO reqVO = randomPojo(SysPostUpdateReqVO.class,
  183 + o -> {
  184 + // 设置更新的 ID
  185 + o.setId(postDO.getId());
  186 + // 模拟 code 重复
  187 + o.setCode(codePostDO.getCode());
  188 + });
  189 + // 调用, 并断言异常
  190 + assertServiceException(() -> postService.updatePost(reqVO), POST_CODE_DUPLICATE);
  191 + }
  192 +
  193 + @SafeVarargs
  194 + private static SysPostDO randomPostDO(Consumer<SysPostDO>... consumers) {
  195 + Consumer<SysPostDO> consumer = (o) -> {
  196 + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
  197 + };
  198 + return randomPojo(SysPostDO.class, ArrayUtils.append(consumer, consumers));
  199 + }
  200 +}
src/test/resources/sql/clean.sql
@@ -9,3 +9,4 @@ DELETE FROM &quot;sys_role_menu&quot;; @@ -9,3 +9,4 @@ DELETE FROM &quot;sys_role_menu&quot;;
9 DELETE FROM "sys_menu"; 9 DELETE FROM "sys_menu";
10 DELETE FROM "sys_dict_type"; 10 DELETE FROM "sys_dict_type";
11 DELETE FROM "sys_user_session"; 11 DELETE FROM "sys_user_session";
  12 +DELETE FROM "sys_post";
src/test/resources/sql/create_tables.sql
@@ -130,6 +130,23 @@ CREATE TABLE `sys_user_session` ( @@ -130,6 +130,23 @@ CREATE TABLE `sys_user_session` (
130 PRIMARY KEY (`id`) 130 PRIMARY KEY (`id`)
131 ) COMMENT '用户在线 Session'; 131 ) COMMENT '用户在线 Session';
132 132
  133 +CREATE TABLE IF NOT EXISTS "sys_post"
  134 +(
  135 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  136 + "code" varchar(64) NOT NULL,
  137 + "name" varchar(50) NOT NULL,
  138 + "sort" integer NOT NULL,
  139 + "status" tinyint NOT NULL,
  140 + "remark" varchar(500) DEFAULT NULL,
  141 + "creator" varchar(64) DEFAULT '',
  142 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  143 + "updater" varchar(64) DEFAULT '',
  144 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  145 + "deleted" bit NOT NULL DEFAULT FALSE,
  146 + PRIMARY KEY ("id")
  147 +) COMMENT '岗位信息表';
  148 +
  149 +
133 CREATE TABLE IF NOT EXISTS "sys_notice" ( 150 CREATE TABLE IF NOT EXISTS "sys_notice" (
134 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, 151 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
135 "title" varchar(50) NOT NULL COMMENT '公告标题', 152 "title" varchar(50) NOT NULL COMMENT '公告标题',