|
@@ -1,31 +1,41 @@
|
|
|
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate;
|
|
|
|
|
|
import cn.hutool.core.map.MapUtil;
|
|
|
+import cn.hutool.extra.spring.SpringUtil;
|
|
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
|
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
|
|
+import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignStartUserHandlerTypeEnum;
|
|
|
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other.BpmTaskCandidateAssignEmptyStrategy;
|
|
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.user.BpmTaskCandidateUserStrategy;
|
|
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmTaskCandidateStrategyEnum;
|
|
|
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
|
|
|
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
|
|
|
+import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
|
|
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
|
|
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
|
|
+import org.flowable.bpmn.model.BpmnModel;
|
|
|
+import org.flowable.bpmn.model.ExtensionElement;
|
|
|
+import org.flowable.bpmn.model.FlowElement;
|
|
|
import org.flowable.bpmn.model.UserTask;
|
|
|
import org.flowable.engine.delegate.DelegateExecution;
|
|
|
+import org.flowable.engine.runtime.ProcessInstance;
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
import org.mockito.Mock;
|
|
|
+import org.mockito.MockedStatic;
|
|
|
import org.mockito.Spy;
|
|
|
+import org.mockito.internal.util.collections.Sets;
|
|
|
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Set;
|
|
|
+import java.util.*;
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
|
|
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
|
|
+import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_NAMESPACE;
|
|
|
+import static org.flowable.bpmn.constants.BpmnXMLConstants.FLOWABLE_EXTENSIONS_PREFIX;
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
|
-import static org.mockito.Mockito.mock;
|
|
|
-import static org.mockito.Mockito.when;
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
|
|
|
/**
|
|
|
* {@link BpmTaskCandidateInvoker} 的单元测试
|
|
@@ -39,44 +49,207 @@ public class BpmTaskCandidateInvokerTest extends BaseMockitoUnitTest {
|
|
|
@Mock
|
|
|
private AdminUserApi adminUserApi;
|
|
|
|
|
|
+ @Mock
|
|
|
+ private BpmProcessInstanceService processInstanceService;
|
|
|
+
|
|
|
@Spy
|
|
|
- private BpmTaskCandidateStrategy strategy ;
|
|
|
+ private BpmTaskCandidateStrategy userStrategy;
|
|
|
+ @Mock
|
|
|
+ private BpmTaskCandidateAssignEmptyStrategy emptyStrategy;
|
|
|
|
|
|
@Spy
|
|
|
- private List<BpmTaskCandidateStrategy> strategyList ;
|
|
|
+ private List<BpmTaskCandidateStrategy> strategyList;
|
|
|
|
|
|
@BeforeEach
|
|
|
public void setUp() {
|
|
|
- strategy = new BpmTaskCandidateUserStrategy(); // 创建strategy实例
|
|
|
- strategyList = Collections.singletonList(strategy); // 创建strategyList
|
|
|
+ userStrategy = new BpmTaskCandidateUserStrategy(); // 创建 strategy 实例
|
|
|
+ when(emptyStrategy.getStrategy()).thenReturn(BpmTaskCandidateStrategyEnum.ASSIGN_EMPTY);
|
|
|
+ strategyList = List.of(userStrategy, emptyStrategy); // 创建 strategyList
|
|
|
taskCandidateInvoker = new BpmTaskCandidateInvoker(strategyList, adminUserApi);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 场景:成功计算到候选人,但是移除了发起人的用户
|
|
|
+ */
|
|
|
@Test
|
|
|
- public void testCalculateUsersByTask() {
|
|
|
- // 准备参数
|
|
|
- String param = "1,2";
|
|
|
- DelegateExecution execution = mock(DelegateExecution.class);
|
|
|
- // mock 方法(DelegateExecution)
|
|
|
- UserTask userTask = mock(UserTask.class);
|
|
|
- when(execution.getCurrentFlowElement()).thenReturn(userTask);
|
|
|
- when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY)))
|
|
|
- .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy().toString());
|
|
|
- when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM)))
|
|
|
- .thenReturn(param);
|
|
|
- // mock 方法(adminUserApi)
|
|
|
- AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
|
|
|
- .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
- AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
|
|
|
- .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
- Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
|
|
|
- .put(user2.getId(), user2).build();
|
|
|
- when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
|
|
|
+ public void testCalculateUsersByTask_some() {
|
|
|
+ try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
|
|
+ // 准备参数
|
|
|
+ String param = "1,2";
|
|
|
+ DelegateExecution execution = mock(DelegateExecution.class);
|
|
|
+ // mock 方法(DelegateExecution)
|
|
|
+ UserTask userTask = mock(UserTask.class);
|
|
|
+ String processInstanceId = randomString();
|
|
|
+ when(execution.getProcessInstanceId()).thenReturn(processInstanceId);
|
|
|
+ when(execution.getCurrentFlowElement()).thenReturn(userTask);
|
|
|
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY)))
|
|
|
+ .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy().toString());
|
|
|
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM)))
|
|
|
+ .thenReturn(param);
|
|
|
+ // mock 方法(adminUserApi)
|
|
|
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
|
|
|
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
|
|
|
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
+ Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
|
|
|
+ .put(user2.getId(), user2).build();
|
|
|
+ when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
|
|
|
+ // mock 移除发起人的用户
|
|
|
+ springUtilMockedStatic.when(() -> SpringUtil.getBean(BpmProcessInstanceService.class))
|
|
|
+ .thenReturn(processInstanceService);
|
|
|
+ ProcessInstance processInstance = mock(ProcessInstance.class);
|
|
|
+ when(processInstanceService.getProcessInstance(eq(processInstanceId))).thenReturn(processInstance);
|
|
|
+ when(processInstance.getStartUserId()).thenReturn("1");
|
|
|
+ mockFlowElementExtensionElement(userTask, BpmnModelConstants.USER_TASK_ASSIGN_START_USER_HANDLER_TYPE,
|
|
|
+ String.valueOf(BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType()));
|
|
|
|
|
|
- // 调用
|
|
|
- Set<Long> results = taskCandidateInvoker.calculateUsersByTask(execution);
|
|
|
- // 断言
|
|
|
- assertEquals(asSet(1L, 2L), results);
|
|
|
+ // 调用
|
|
|
+ Set<Long> results = taskCandidateInvoker.calculateUsersByTask(execution);
|
|
|
+ // 断言
|
|
|
+ assertEquals(asSet(2L), results);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景:没有计算到候选人,但是被禁用移除,最终通过 empty 进行分配
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCalculateUsersByTask_none() {
|
|
|
+ try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
|
|
|
+ // 准备参数
|
|
|
+ String param = "1,2";
|
|
|
+ DelegateExecution execution = mock(DelegateExecution.class);
|
|
|
+ // mock 方法(DelegateExecution)
|
|
|
+ UserTask userTask = mock(UserTask.class);
|
|
|
+ String processInstanceId = randomString();
|
|
|
+ when(execution.getProcessInstanceId()).thenReturn(processInstanceId);
|
|
|
+ when(execution.getCurrentFlowElement()).thenReturn(userTask);
|
|
|
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_STRATEGY)))
|
|
|
+ .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy().toString());
|
|
|
+ when(userTask.getAttributeValue(eq(BpmnModelConstants.NAMESPACE), eq(BpmnModelConstants.USER_TASK_CANDIDATE_PARAM)))
|
|
|
+ .thenReturn(param);
|
|
|
+ // mock 方法(adminUserApi)
|
|
|
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
|
|
|
+ .setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
|
|
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
|
|
|
+ .setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
|
|
+ Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
|
|
|
+ .put(user2.getId(), user2).build();
|
|
|
+ when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
|
|
|
+ // mock 方法(empty)
|
|
|
+ when(emptyStrategy.calculateUsersByTask(same(execution), same(param)))
|
|
|
+ .thenReturn(Sets.newSet(2L));
|
|
|
+ // mock 移除发起人的用户
|
|
|
+ springUtilMockedStatic.when(() -> SpringUtil.getBean(BpmProcessInstanceService.class))
|
|
|
+ .thenReturn(processInstanceService);
|
|
|
+ ProcessInstance processInstance = mock(ProcessInstance.class);
|
|
|
+ when(processInstanceService.getProcessInstance(eq(processInstanceId))).thenReturn(processInstance);
|
|
|
+ when(processInstance.getStartUserId()).thenReturn("1");
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ Set<Long> results = taskCandidateInvoker.calculateUsersByTask(execution);
|
|
|
+ // 断言
|
|
|
+ assertEquals(asSet(2L), results);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景:没有计算到候选人,但是被禁用移除,最终通过 empty 进行分配
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCalculateUsersByActivity_some() {
|
|
|
+ try (MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
|
|
|
+ // 准备参数
|
|
|
+ String param = "1,2";
|
|
|
+ BpmnModel bpmnModel = mock(BpmnModel.class);
|
|
|
+ String activityId = randomString();
|
|
|
+ Long startUserId = 1L;
|
|
|
+ String processDefinitionId = randomString();
|
|
|
+ Map<String, Object> processVariables = new HashMap<>();
|
|
|
+ // mock 方法(DelegateExecution)
|
|
|
+ UserTask userTask = mock(UserTask.class);
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseCandidateStrategy(same(userTask)))
|
|
|
+ .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy());
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseCandidateParam(same(userTask)))
|
|
|
+ .thenReturn(param);
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.getFlowElementById(same(bpmnModel), eq(activityId))).thenReturn(userTask);
|
|
|
+ // mock 方法(adminUserApi)
|
|
|
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
|
|
|
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
|
|
|
+ .setStatus(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
+ Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
|
|
|
+ .put(user2.getId(), user2).build();
|
|
|
+ when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
|
|
|
+ // mock 移除发起人的用户
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignStartUserHandlerType(same(userTask)))
|
|
|
+ .thenReturn(BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType());
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ Set<Long> results = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId,
|
|
|
+ startUserId, processDefinitionId, processVariables);
|
|
|
+ // 断言
|
|
|
+ assertEquals(asSet(2L), results);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 场景:成功计算到候选人,但是移除了发起人的用户
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testCalculateUsersByActivity_none() {
|
|
|
+ try (MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
|
|
|
+ // 准备参数
|
|
|
+ String param = "1,2";
|
|
|
+ BpmnModel bpmnModel = mock(BpmnModel.class);
|
|
|
+ String activityId = randomString();
|
|
|
+ Long startUserId = 1L;
|
|
|
+ String processDefinitionId = randomString();
|
|
|
+ Map<String, Object> processVariables = new HashMap<>();
|
|
|
+ // mock 方法(DelegateExecution)
|
|
|
+ UserTask userTask = mock(UserTask.class);
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseCandidateStrategy(same(userTask)))
|
|
|
+ .thenReturn(BpmTaskCandidateStrategyEnum.USER.getStrategy());
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseCandidateParam(same(userTask)))
|
|
|
+ .thenReturn(param);
|
|
|
+ bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.getFlowElementById(same(bpmnModel), eq(activityId))).thenReturn(userTask);
|
|
|
+ // mock 方法(adminUserApi)
|
|
|
+ AdminUserRespDTO user1 = randomPojo(AdminUserRespDTO.class, o -> o.setId(1L)
|
|
|
+ .setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
|
|
+ AdminUserRespDTO user2 = randomPojo(AdminUserRespDTO.class, o -> o.setId(2L)
|
|
|
+ .setStatus(CommonStatusEnum.DISABLE.getStatus()));
|
|
|
+ Map<Long, AdminUserRespDTO> userMap = MapUtil.builder(user1.getId(), user1)
|
|
|
+ .put(user2.getId(), user2).build();
|
|
|
+ when(adminUserApi.getUserMap(eq(asSet(1L, 2L)))).thenReturn(userMap);
|
|
|
+ // mock 方法(empty)
|
|
|
+ when(emptyStrategy.calculateUsersByActivity(same(bpmnModel), eq(activityId),
|
|
|
+ eq(param), same(startUserId), same(processDefinitionId), same(processVariables)))
|
|
|
+ .thenReturn(Sets.newSet(2L));
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ Set<Long> results = taskCandidateInvoker.calculateUsersByActivity(bpmnModel, activityId,
|
|
|
+ startUserId, processDefinitionId, processVariables);
|
|
|
+ // 断言
|
|
|
+ assertEquals(asSet(2L), results);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void mockFlowElementExtensionElement(FlowElement element, String name, String value) {
|
|
|
+ if (value == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ ExtensionElement extensionElement = new ExtensionElement();
|
|
|
+ extensionElement.setNamespace(FLOWABLE_EXTENSIONS_NAMESPACE);
|
|
|
+ extensionElement.setNamespacePrefix(FLOWABLE_EXTENSIONS_PREFIX);
|
|
|
+ extensionElement.setElementText(value);
|
|
|
+ extensionElement.setName(name);
|
|
|
+ // mock
|
|
|
+ Map<String, List<ExtensionElement>> extensionElements = element.getExtensionElements();
|
|
|
+ if (extensionElements == null) {
|
|
|
+ extensionElements = new LinkedHashMap<>();
|
|
|
+ }
|
|
|
+ extensionElements.put(name, Collections.singletonList(extensionElement));
|
|
|
+ when(element.getExtensionElements()).thenReturn(extensionElements);
|
|
|
}
|
|
|
|
|
|
@Test
|