多模块重构 8:bom 模块的调整

This commit is contained in:
YunaiV
2022-01-31 22:55:48 +08:00
parent d45213fe2a
commit 510917c5ed
179 changed files with 91 additions and 103 deletions

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.adminserver;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
/**
* 依赖内存 DB 的单元测试
*
* 注意Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
*
* @author 芋道源码
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
public class BaseDbUnitTest {
@Import({
// DB 配置类
YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
DataSourceAutoConfiguration.class, // Spring DB 自动配置类
DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
DruidDataSourceAutoConfigure.class, // Druid 自动配置类
// MyBatis 配置类
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
})
public static class Application {
}
}

View File

@@ -0,0 +1,213 @@
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.adminserver.modules.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.adminserver.modules.bpm.enums.definition.BpmTaskRuleScriptEnum;
import cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.BpmTaskAssignScript;
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmTaskAssignRuleService;
import cn.iocoder.yudao.coreservice.modules.bpm.api.group.BpmUserGroupServiceApi;
import cn.iocoder.yudao.coreservice.modules.bpm.api.group.dto.BpmUserGroupDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.module.system.service.dept.SysDeptCoreService;
import cn.iocoder.yudao.module.system.service.permission.SysPermissionCoreService;
import cn.iocoder.yudao.module.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Collections.singleton;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
public class BpmUserTaskActivitiBehaviorTest extends BaseMockitoUnitTest {
@InjectMocks
private BpmUserTaskActivitiBehavior behavior;
@Mock
private BpmTaskAssignRuleService bpmTaskRuleService;
@Mock
private SysPermissionCoreService permissionCoreService;
@Mock
private SysDeptCoreService deptCoreService;
@Mock
private BpmUserGroupServiceApi userGroupServiceApi;
@Mock
private SysUserCoreService userCoreService;
@Test
public void testCalculateTaskCandidateUsers_Role() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.ROLE.getType());
// mock 方法
when(permissionCoreService.getUserRoleIdListByRoleIds(eq(rule.getOptions())))
.thenReturn(asSet(11L, 22L));
mockGetUserMap(asSet(11L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 22L), results);
}
@Test
public void testCalculateTaskCandidateUsers_DeptMember() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType());
// mock 方法
List<SysUserDO> users = CollectionUtils.convertList(asSet(11L, 22L),
id -> new SysUserDO().setId(id));
when(userCoreService.getUsersByDeptIds(eq(rule.getOptions()))).thenReturn(users);
mockGetUserMap(asSet(11L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 22L), results);
}
@Test
public void testCalculateTaskCandidateUsers_DeptLeader() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType());
// mock 方法
SysDeptDO dept1 = randomPojo(SysDeptDO.class, o -> o.setLeaderUserId(11L));
SysDeptDO dept2 = randomPojo(SysDeptDO.class, o -> o.setLeaderUserId(22L));
when(deptCoreService.getDepts(eq(rule.getOptions()))).thenReturn(Arrays.asList(dept1, dept2));
mockGetUserMap(asSet(11L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 22L), results);
}
@Test
public void testCalculateTaskCandidateUsers_Post() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.POST.getType());
// mock 方法
List<SysUserDO> users = CollectionUtils.convertList(asSet(11L, 22L),
id -> new SysUserDO().setId(id));
when(userCoreService.getUsersByPostIds(eq(rule.getOptions()))).thenReturn(users);
mockGetUserMap(asSet(11L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 22L), results);
}
@Test
public void testCalculateTaskCandidateUsers_User() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.USER.getType());
// mock 方法
mockGetUserMap(asSet(1L, 2L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(1L, 2L), results);
}
@Test
public void testCalculateTaskCandidateUsers_UserGroup() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(1L, 2L))
.setType(BpmTaskAssignRuleTypeEnum.USER_GROUP.getType());
// mock 方法
BpmUserGroupDTO userGroup1 = randomPojo(BpmUserGroupDTO.class, o -> o.setMemberUserIds(asSet(11L, 12L)));
BpmUserGroupDTO userGroup2 = randomPojo(BpmUserGroupDTO.class, o -> o.setMemberUserIds(asSet(21L, 22L)));
when(userGroupServiceApi.getUserGroupList(eq(rule.getOptions()))).thenReturn(Arrays.asList(userGroup1, userGroup2));
mockGetUserMap(asSet(11L, 12L, 21L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 12L, 21L, 22L), results);
}
@Test
public void testCalculateTaskCandidateUsers_Script() {
// 准备参数
BpmTaskAssignRuleDO rule = new BpmTaskAssignRuleDO().setOptions(asSet(20L, 21L))
.setType(BpmTaskAssignRuleTypeEnum.SCRIPT.getType());
// mock 方法
BpmTaskAssignScript script1 = new BpmTaskAssignScript() {
@Override
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
return singleton(11L);
}
@Override
public BpmTaskRuleScriptEnum getEnum() {
return BpmTaskRuleScriptEnum.LEADER_X1;
}
};
BpmTaskAssignScript script2 = new BpmTaskAssignScript() {
@Override
public Set<Long> calculateTaskCandidateUsers(TaskEntity task) {
return singleton(22L);
}
@Override
public BpmTaskRuleScriptEnum getEnum() {
return BpmTaskRuleScriptEnum.LEADER_X2;
}
};
behavior.setScripts(Arrays.asList(script1, script2));
mockGetUserMap(asSet(11L, 22L));
// 调用
Set<Long> results = behavior.calculateTaskCandidateUsers(null, rule);
// 断言
assertEquals(asSet(11L, 22L), results);
}
@Test
public void testRemoveDisableUsers() {
// 准备参数. 1L 可以找到2L 是禁用的3L 找不到
Set<Long> assigneeUserIds = asSet(1L, 2L, 3L);
// mock 方法
SysUserDO user1 = randomPojo(SysUserDO.class, o -> o.setId(1L)
.setStatus(CommonStatusEnum.ENABLE.getStatus()));
SysUserDO user2 = randomPojo(SysUserDO.class, o -> o.setId(2L)
.setStatus(CommonStatusEnum.DISABLE.getStatus()));
Map<Long, SysUserDO> userMap = MapUtil.builder(user1.getId(), user1)
.put(user2.getId(), user2).build();
when(userCoreService.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
// 调用
behavior.removeDisableUsers(assigneeUserIds);
// 断言
assertEquals(asSet(1L), assigneeUserIds);
}
private void mockGetUserMap(Set<Long> assigneeUserIds) {
Map<Long, SysUserDO> userMap = CollectionUtils.convertMap(assigneeUserIds, id -> id,
id -> new SysUserDO().setId(id).setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(userCoreService.getUserMap(eq(assigneeUserIds))).thenReturn(userMap);
}
}

View File

@@ -0,0 +1,93 @@
package cn.iocoder.yudao.adminserver.modules.bpm.framework.activiti.core.behavior.script.impl;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.SysDeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.yudao.module.system.service.dept.SysDeptCoreService;
import cn.iocoder.yudao.module.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
@InjectMocks
private BpmTaskAssignLeaderX2Script script;
@Mock
private SysUserCoreService userCoreService;
@Mock
private SysDeptCoreService deptCoreService;
@Test
public void testCalculateTaskCandidateUsers_noDept() {
// 准备参数
TaskEntity task = buildTaskEntity(1L);
// mock 方法(startUser)
SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L));
when(userCoreService.getUser(eq(1L))).thenReturn(startUser);
// 调用
Set<Long> result = script.calculateTaskCandidateUsers(task);
// 断言
assertEquals(0, result.size());
}
@Test
public void testCalculateTaskCandidateUsers_noParentDept() {
// 准备参数
TaskEntity task = buildTaskEntity(1L);
// mock 方法(startUser)
SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L));
when(userCoreService.getUser(eq(1L))).thenReturn(startUser);
SysDeptDO startUserDept = randomPojo(SysDeptDO.class, o -> o.setId(10L).setParentId(100L)
.setLeaderUserId(20L));
when(deptCoreService.getDept(eq(10L))).thenReturn(startUserDept);
// 调用
Set<Long> result = script.calculateTaskCandidateUsers(task);
// 断言
assertEquals(asSet(20L), result);
}
@Test
public void testCalculateTaskCandidateUsers_existParentDept() {
// 准备参数
TaskEntity task = buildTaskEntity(1L);
// mock 方法(startUser)
SysUserDO startUser = randomPojo(SysUserDO.class, o -> o.setDeptId(10L));
when(userCoreService.getUser(eq(1L))).thenReturn(startUser);
SysDeptDO startUserDept = randomPojo(SysDeptDO.class, o -> o.setId(10L).setParentId(100L)
.setLeaderUserId(20L));
when(deptCoreService.getDept(eq(10L))).thenReturn(startUserDept);
// mock 方法(父 dept
SysDeptDO parentDept = randomPojo(SysDeptDO.class, o -> o.setId(100L).setParentId(1000L)
.setLeaderUserId(200L));
when(deptCoreService.getDept(eq(100L))).thenReturn(parentDept);
// 调用
Set<Long> result = script.calculateTaskCandidateUsers(task);
// 断言
assertEquals(asSet(200L), result);
}
@SuppressWarnings("SameParameterValue")
private TaskEntity buildTaskEntity(Long startUserId) {
TaskEntityImpl task = new TaskEntityImpl();
task.setProcessInstance(new ExecutionEntityImpl());
task.getProcessInstance().setStartUserId(String.valueOf(startUserId));
return task;
}
}

View File

@@ -0,0 +1 @@
package cn.iocoder.yudao.adminserver.modules.bpm.service;

View File

@@ -0,0 +1,38 @@
spring:
main:
lazy-initialization: true # 开启懒加载,加快速度
banner-mode: off # 单元测试,禁用 Banner
--- #################### 数据库相关配置 ####################
spring:
# 数据源配置项
datasource:
name: ruoyi-vue-pro
url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式DATABASE_TO_UPPER 配置表和字段使用小写
driver-class-name: org.h2.Driver
username: sa
password:
schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具
druid:
async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
initial-size: 1 # 单元测试,配置为 1提升启动速度
mybatis:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
--- #################### 定时任务相关配置 ####################
--- #################### 配置中心相关配置 ####################
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项(单元测试,禁用 Lock4j
# Resilience4j 配置项
--- #################### 监控相关配置 ####################
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置

View File

@@ -0,0 +1,35 @@
spring:
application:
name: yudao-module-bpm-service
# Jackson 配置项
jackson:
serialization:
write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳
write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
fail-on-empty-beans: false # 允许序列化无属性的 Bean
# MyBatis Plus 的配置项
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
global-config:
db-config:
id-type: AUTO # 自增 ID
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: ${yudao.core-service.base-package}.modules.*.dal.dataobject
--- #################### 芋道相关配置 ####################
yudao:
info:
version: 1.0.0
base-package: cn.iocoder.yudao.adminserver
core-service:
base-package: cn.iocoder.yudao.coreservice
debug: false

View File

@@ -0,0 +1,4 @@
<configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
</configuration>

View File

@@ -0,0 +1,2 @@
-- bpm 开头的 DB
DELETE FROM "bpm_form";

View File

@@ -0,0 +1,28 @@
CREATE TABLE IF NOT EXISTS "bpm_form" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(63) NOT NULL,
"status" tinyint NOT NULL,
"fields" varchar(255) NOT NULL,
"conf" varchar(255) NOT NULL,
"remark" varchar(255),
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '动态表单';
CREATE TABLE IF NOT EXISTS "bpm_user_group" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(63) NOT NULL,
"description" varchar(255) NOT NULL,
"status" tinyint NOT NULL,
"member_user_ids" varchar(255) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '用户组';