mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 04:39:00 +08:00
refactor(pigx-flow): 移除测试文件并禁用 JimuReport 模块
- 删除 `MultiInstanceHandlerTests`、`ProcessNodeRecordServiceImplTests`、`ProcessTaskControllerTests`、`TaskServiceDelegateParticipationTests`、`TaskServiceImplTests` 五个测试类 - 注释 `pigx-visual/pom.xml` 中的 `pigx-jimu-platform` 模块,并添加启用说明注释
This commit is contained in:
1 parent
55df29df99
commit
7461394f99
6 files changed
+2
-700
No files matched your search
-49
@@ -1,49 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.controller;
|
||||
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.flow.dto.AddSignTaskDto;
|
||||
import com.pig4cloud.pigx.flow.service.ITaskService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
class ProcessTaskControllerTests {
|
||||
|
||||
@Test
|
||||
void originalApproverCanRequestBatchAddSignThroughPublicApi() throws Exception {
|
||||
ITaskService taskService = mock(ITaskService.class);
|
||||
when(taskService.addSign(org.mockito.ArgumentMatchers.any(AddSignTaskDto.class))).thenReturn(R.ok());
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new ProcessTaskController(taskService)).build();
|
||||
|
||||
mockMvc.perform(post("/task/addSign")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"taskId": "12501",
|
||||
"targetUserIdList": [31, 32],
|
||||
"reason": "需要法务和财务共同确认"
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0));
|
||||
|
||||
ArgumentCaptor<AddSignTaskDto> captor = ArgumentCaptor.forClass(AddSignTaskDto.class);
|
||||
verify(taskService).addSign(captor.capture());
|
||||
assertThat(captor.getValue().getTaskId()).isEqualTo("12501");
|
||||
assertThat(captor.getValue().getTargetUserIdList()).containsExactly(31L, 32L);
|
||||
assertThat(captor.getValue().getReason()).isEqualTo("需要法务和财务共同确认");
|
||||
}
|
||||
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.service.impl;
|
||||
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.flow.constant.NodeStatusEnum;
|
||||
import com.pig4cloud.pigx.flow.dto.ProcessNodeRecordParamDto;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessNodeRecord;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ProcessNodeRecordServiceImplTests {
|
||||
|
||||
@Mock
|
||||
private LambdaQueryChainWrapper<ProcessNodeRecord> activeRecordQuery;
|
||||
|
||||
private ProcessNodeRecordServiceImpl service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
service = spy(new ProcessNodeRecordServiceImpl());
|
||||
doReturn(activeRecordQuery).when(service).lambdaQuery();
|
||||
when(activeRecordQuery.eq(any(SFunction.class), any())).thenReturn(activeRecordQuery);
|
||||
when(activeRecordQuery.orderByAsc(any(SFunction.class))).thenReturn(activeRecordQuery);
|
||||
when(activeRecordQuery.last(anyString())).thenReturn(activeRecordQuery);
|
||||
}
|
||||
|
||||
@Test
|
||||
void startReusesActiveRecordForSameProcessNodeRound() {
|
||||
ProcessNodeRecord existing = new ProcessNodeRecord()
|
||||
.setId(101L)
|
||||
.setProcessInstanceId("process-1")
|
||||
.setNodeId("approve-1")
|
||||
.setStatus(NodeStatusEnum.JXZ.getCode());
|
||||
when(activeRecordQuery.one()).thenReturn(existing);
|
||||
|
||||
R result = service.start(request());
|
||||
|
||||
assertThat(result.getCode()).isZero();
|
||||
assertThat(result.getData()).isEqualTo(101L);
|
||||
verify(service, never()).save(any(ProcessNodeRecord.class));
|
||||
}
|
||||
|
||||
private ProcessNodeRecordParamDto request() {
|
||||
ProcessNodeRecordParamDto request = new ProcessNodeRecordParamDto();
|
||||
request.setFlowId("flow-1");
|
||||
request.setProcessInstanceId("process-1");
|
||||
request.setNodeId("approve-1");
|
||||
request.setNodeName("会签审批");
|
||||
request.setExecutionId("execution-2");
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
-138
@@ -1,138 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysUser;
|
||||
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.common.security.service.PigxUser;
|
||||
import com.pig4cloud.pigx.flow.constant.NodeStatusEnum;
|
||||
import com.pig4cloud.pigx.flow.constant.ProcessInstanceConstant;
|
||||
import com.pig4cloud.pigx.flow.dto.TaskParamDto;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessNodeRecord;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessNodeRecordAssignUser;
|
||||
import com.pig4cloud.pigx.flow.mapper.ProcessNodeRecordMapper;
|
||||
import com.pig4cloud.pigx.flow.mapper.ProcessTaskAddSignRecordMapper;
|
||||
import com.pig4cloud.pigx.flow.service.IFlowableEngineService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessCopyService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessInstanceRecordService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeDataService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeRecordAssignUserService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeRecordService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessService;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskQuery;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TaskServiceDelegateParticipationTests {
|
||||
|
||||
private static final long USER_ID = 11L;
|
||||
private static final long TARGET_USER_ID = 31L;
|
||||
private static final long TENANT_ID = 1L;
|
||||
private static final long NODE_RECORD_ID = 101L;
|
||||
private static final String TASK_ID = "task-1";
|
||||
private static final String PROCESS_INSTANCE_ID = "process-1";
|
||||
private static final String NODE_ID = "approve-1";
|
||||
|
||||
@Mock private IProcessService processService;
|
||||
@Mock private IProcessCopyService processCopyService;
|
||||
@Mock private IProcessNodeDataService nodeDataService;
|
||||
@Mock private IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
|
||||
@Mock private IProcessInstanceRecordService processInstanceRecordService;
|
||||
@Mock private IProcessNodeRecordService processNodeRecordService;
|
||||
@Mock private IFlowableEngineService flowableEngineService;
|
||||
@Mock private TaskService taskService;
|
||||
@Mock private HistoryService historyService;
|
||||
@Mock private RuntimeService runtimeService;
|
||||
@Mock private ObjectMapper objectMapper;
|
||||
@Mock private RemoteUserService remoteUserService;
|
||||
@Mock private ProcessNodeRecordMapper processNodeRecordMapper;
|
||||
@Mock private ProcessTaskAddSignRecordMapper processTaskAddSignRecordMapper;
|
||||
@Mock(answer = Answers.RETURNS_SELF) private TaskQuery taskQuery;
|
||||
@Mock private Task task;
|
||||
@Mock private BaseMapper<ProcessNodeRecordAssignUser> assignmentBaseMapper;
|
||||
|
||||
@InjectMocks private TaskServiceImpl taskServiceImpl;
|
||||
|
||||
@BeforeEach
|
||||
void setCurrentUserAndTenant() {
|
||||
PigxUser user = new PigxUser(USER_ID, "approver", List.of(), null, List.of(), List.of(), null, null,
|
||||
"审批人", "审批人", null, TENANT_ID, "password", true, true, "sys", true,
|
||||
LocalDateTime.now(), true, List.of());
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(UsernamePasswordAuthenticationToken.authenticated(user, "password", List.of()));
|
||||
TenantContextHolder.setTenantId(TENANT_ID);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearCurrentUserAndTenant() {
|
||||
SecurityContextHolder.clearContext();
|
||||
TenantContextHolder.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void delegateRejectsUserAlreadyParticipatingInCurrentRound() {
|
||||
when(taskService.createTaskQuery()).thenReturn(taskQuery);
|
||||
when(taskQuery.singleResult()).thenReturn(task);
|
||||
when(task.getId()).thenReturn(TASK_ID);
|
||||
when(task.getProcessInstanceId()).thenReturn(PROCESS_INSTANCE_ID);
|
||||
when(task.getTaskDefinitionKey()).thenReturn(NODE_ID);
|
||||
when(processNodeRecordAssignUserService.lambdaQuery())
|
||||
.thenAnswer(invocation -> new LambdaQueryChainWrapper<>(assignmentBaseMapper));
|
||||
when(assignmentBaseMapper.selectOne(any())).thenReturn(originalAssignment());
|
||||
when(assignmentBaseMapper.selectList(any())).thenReturn(List.of(originalAssignment(), targetAssignment()));
|
||||
when(processNodeRecordMapper.selectActiveByIdForUpdate(NODE_RECORD_ID, PROCESS_INSTANCE_ID, NODE_ID, TENANT_ID))
|
||||
.thenReturn(new ProcessNodeRecord().setId(NODE_RECORD_ID));
|
||||
TaskParamDto request = new TaskParamDto();
|
||||
request.setTaskId(TASK_ID);
|
||||
request.setTargetUserIdList(List.of(TARGET_USER_ID));
|
||||
R result = taskServiceImpl.delegateTask(request);
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("委托目标已参与当前会签");
|
||||
verify(flowableEngineService, never()).delegateTask(any(TaskParamDto.class));
|
||||
}
|
||||
|
||||
private ProcessNodeRecordAssignUser originalAssignment() {
|
||||
return new ProcessNodeRecordAssignUser()
|
||||
.setNodeRecordId(NODE_RECORD_ID)
|
||||
.setTaskId(TASK_ID)
|
||||
.setUserId(USER_ID)
|
||||
.setInitialUserId(USER_ID)
|
||||
.setAssignmentOrigin(ProcessInstanceConstant.ASSIGNMENT_ORIGIN_ORIGINAL)
|
||||
.setStatus(NodeStatusEnum.JXZ.getCode());
|
||||
}
|
||||
|
||||
private ProcessNodeRecordAssignUser targetAssignment() {
|
||||
return new ProcessNodeRecordAssignUser()
|
||||
.setNodeRecordId(NODE_RECORD_ID)
|
||||
.setTaskId("task-2")
|
||||
.setUserId(TARGET_USER_ID)
|
||||
.setStatus(NodeStatusEnum.JXZ.getCode());
|
||||
}
|
||||
|
||||
}
|
||||
-405
@@ -1,405 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysUser;
|
||||
import com.pig4cloud.pigx.admin.api.feign.RemoteUserService;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.common.security.service.PigxUser;
|
||||
import com.pig4cloud.pigx.flow.constant.NodeStatusEnum;
|
||||
import com.pig4cloud.pigx.flow.constant.ProcessInstanceConstant;
|
||||
import com.pig4cloud.pigx.flow.dto.AddSignResultDto;
|
||||
import com.pig4cloud.pigx.flow.dto.AddSignTaskDto;
|
||||
import com.pig4cloud.pigx.flow.dto.Node;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessInstanceRecord;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessNodeRecord;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessNodeRecordAssignUser;
|
||||
import com.pig4cloud.pigx.flow.entity.ProcessTaskAddSignRecord;
|
||||
import com.pig4cloud.pigx.flow.mapper.ProcessNodeRecordMapper;
|
||||
import com.pig4cloud.pigx.flow.mapper.ProcessTaskAddSignRecordMapper;
|
||||
import com.pig4cloud.pigx.flow.service.IFlowableEngineService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessCopyService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessInstanceRecordService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeDataService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeRecordAssignUserService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeRecordService;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessService;
|
||||
import com.pig4cloud.pigx.flow.service.ITaskService;
|
||||
import org.flowable.common.engine.api.FlowableOptimisticLockingException;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.flowable.task.api.TaskQuery;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TaskServiceImplTests {
|
||||
|
||||
private static final long USER_ID = 11L;
|
||||
|
||||
private static final long TENANT_ID = 1L;
|
||||
|
||||
private static final long TARGET_USER_ID = 31L;
|
||||
|
||||
private static final long NODE_RECORD_ID = 101L;
|
||||
|
||||
private static final long ADD_SIGN_RECORD_ID = 901L;
|
||||
|
||||
private static final String TASK_ID = "12501";
|
||||
|
||||
private static final String ADDED_TASK_ID = "12502";
|
||||
|
||||
private static final String FLOW_ID = "flow-1";
|
||||
|
||||
private static final String PROCESS_DEFINITION_ID = FLOW_ID + ":1:deployment";
|
||||
|
||||
private static final String PROCESS_INSTANCE_ID = "process-1";
|
||||
|
||||
private static final String NODE_ID = "approve-1";
|
||||
|
||||
@Mock
|
||||
private IProcessService processService;
|
||||
@Mock
|
||||
private IProcessCopyService processCopyService;
|
||||
@Mock
|
||||
private IProcessNodeDataService nodeDataService;
|
||||
@Mock
|
||||
private IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
|
||||
@Mock
|
||||
private IProcessInstanceRecordService processInstanceRecordService;
|
||||
@Mock
|
||||
private IProcessNodeRecordService processNodeRecordService;
|
||||
@Mock
|
||||
private IFlowableEngineService flowableEngineService;
|
||||
@Mock
|
||||
private TaskService taskService;
|
||||
@Mock
|
||||
private HistoryService historyService;
|
||||
@Mock
|
||||
private RuntimeService runtimeService;
|
||||
@Spy
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
@Mock
|
||||
private RemoteUserService remoteUserService;
|
||||
@Mock
|
||||
private ProcessNodeRecordMapper processNodeRecordMapper;
|
||||
@Mock
|
||||
private ProcessTaskAddSignRecordMapper processTaskAddSignRecordMapper;
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private TaskQuery taskQuery;
|
||||
@Mock
|
||||
private BaseMapper<ProcessInstanceRecord> processInstanceBaseMapper;
|
||||
@Mock
|
||||
private BaseMapper<ProcessNodeRecordAssignUser> assignmentBaseMapper;
|
||||
@Mock
|
||||
private Task sourceTask;
|
||||
@Mock
|
||||
private Task addedTask;
|
||||
@Mock
|
||||
private Execution addedExecution;
|
||||
|
||||
@InjectMocks
|
||||
private TaskServiceImpl taskServiceImpl;
|
||||
|
||||
@BeforeEach
|
||||
void setCurrentUserAndTenant() {
|
||||
PigxUser user = new PigxUser(USER_ID, "approver", List.of(), null, List.of(), List.of(), null, null,
|
||||
"审批人", "审批人", null, TENANT_ID, "password", true, true, "sys", true,
|
||||
LocalDateTime.now(), true, List.of());
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(UsernamePasswordAuthenticationToken.authenticated(user, "password", List.of()));
|
||||
TenantContextHolder.setTenantId(TENANT_ID);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearCurrentUserAndTenant() {
|
||||
SecurityContextHolder.clearContext();
|
||||
TenantContextHolder.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsEmptyTargetBatch() {
|
||||
AddSignTaskDto request = request(List.of(), "需要共同确认");
|
||||
|
||||
R result = taskServiceImpl.addSign(request);
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("请选择加签人员");
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsDuplicateTargetUsers() {
|
||||
AddSignTaskDto request = request(List.of(31L, 31L), "需要共同确认");
|
||||
|
||||
R result = taskServiceImpl.addSign(request);
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("加签人员不能重复");
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsReasonOutsideLengthLimit() {
|
||||
AddSignTaskDto request = request(List.of(31L), "短");
|
||||
|
||||
R result = taskServiceImpl.addSign(request);
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("加签原因需为 2~100 字");
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignCreatesTaskAndAuditSnapshotForEligibleApprover() {
|
||||
prepareTaskAndNode(addedTask);
|
||||
prepareOriginalApprover();
|
||||
prepareTargetValidation(List.of(originalAssignment()), validUser(TARGET_USER_ID, TENANT_ID));
|
||||
prepareAuditInsert();
|
||||
when(runtimeService.addMultiInstanceExecution(eq(NODE_ID), eq(PROCESS_INSTANCE_ID), anyMap()))
|
||||
.thenReturn(addedExecution);
|
||||
when(assignmentBaseMapper.selectCount(any())).thenReturn(1L);
|
||||
|
||||
R result = taskServiceImpl.addSign(request(List.of(TARGET_USER_ID), "需要共同确认"));
|
||||
|
||||
assertThat(result.getCode()).isZero();
|
||||
assertThat(result.getData()).isInstanceOf(AddSignResultDto.class);
|
||||
AddSignResultDto addSignResult = (AddSignResultDto) result.getData();
|
||||
assertThat(addSignResult.getRecordId()).isEqualTo(ADD_SIGN_RECORD_ID);
|
||||
assertThat(addSignResult.getTasks()).hasSize(1);
|
||||
assertThat(addSignResult.getTasks().get(0).getTaskId()).isEqualTo(ADDED_TASK_ID);
|
||||
assertThat(addSignResult.getTasks().get(0).getUserId()).isEqualTo(TARGET_USER_ID);
|
||||
|
||||
ArgumentCaptor<ProcessTaskAddSignRecord> recordCaptor = ArgumentCaptor
|
||||
.forClass(ProcessTaskAddSignRecord.class);
|
||||
verify(processTaskAddSignRecordMapper).insert(recordCaptor.capture());
|
||||
ProcessTaskAddSignRecord record = recordCaptor.getValue();
|
||||
assertThat(record.getSourceTaskId()).isEqualTo(TASK_ID);
|
||||
assertThat(record.getAddedByUserId()).isEqualTo(USER_ID);
|
||||
assertThat(record.getTargetUserIds()).isEqualTo("[31]");
|
||||
assertThat(record.getParticipantUserIdsBefore()).isEqualTo("[11]");
|
||||
assertThat(record.getParticipantUserIdsAfter()).isEqualTo("[11,31]");
|
||||
verify(processTaskAddSignRecordMapper).updateById(record);
|
||||
verify(processNodeRecordMapper).selectActiveByIdForUpdate(NODE_RECORD_ID, PROCESS_INSTANCE_ID, NODE_ID,
|
||||
TENANT_ID);
|
||||
verify(runtimeService).addMultiInstanceExecution(eq(NODE_ID), eq(PROCESS_INSTANCE_ID),
|
||||
argThat(variables -> Long.valueOf(TARGET_USER_ID).equals(variables.get(NODE_ID + "_assignee_temp"))
|
||||
&& Long.valueOf(ADD_SIGN_RECORD_ID)
|
||||
.equals(variables.get(ProcessInstanceConstant.VAR_ADD_SIGN_RECORD_ID))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsProcessStarterEvenWhenStarterOwnsTask() {
|
||||
prepareTaskAndNode(null);
|
||||
prepareActiveAssignment();
|
||||
when(processInstanceRecordService.lambdaQuery())
|
||||
.thenAnswer(invocation -> new LambdaQueryChainWrapper<>(processInstanceBaseMapper));
|
||||
when(processInstanceBaseMapper.selectCount(any())).thenReturn(1L);
|
||||
|
||||
R result = taskServiceImpl.addSign(request(List.of(TARGET_USER_ID), "需要共同确认"));
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("流程发起人不能发起加签");
|
||||
verify(processTaskAddSignRecordMapper, never()).insert(any(ProcessTaskAddSignRecord.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsTargetUserFromAnotherTenant() {
|
||||
prepareTaskAndNode(null);
|
||||
prepareOriginalApprover();
|
||||
prepareTargetValidation(List.of(originalAssignment()), validUser(TARGET_USER_ID, TENANT_ID + 1));
|
||||
|
||||
R result = taskServiceImpl.addSign(request(List.of(TARGET_USER_ID), "需要共同确认"));
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("加签用户不存在或不属于当前租户");
|
||||
verify(processTaskAddSignRecordMapper, never()).insert(any(ProcessTaskAddSignRecord.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRejectsUserAlreadyParticipatingInCurrentCountersign() {
|
||||
prepareTaskAndNode(null);
|
||||
prepareOriginalApprover();
|
||||
ProcessNodeRecordAssignUser existingParticipant = new ProcessNodeRecordAssignUser()
|
||||
.setNodeRecordId(NODE_RECORD_ID)
|
||||
.setUserId(TARGET_USER_ID);
|
||||
prepareTargetValidation(List.of(originalAssignment(), existingParticipant),
|
||||
validUser(TARGET_USER_ID, TENANT_ID));
|
||||
|
||||
R result = taskServiceImpl.addSign(request(List.of(TARGET_USER_ID), "需要共同确认"));
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("用户已参与当前会签:目标审批人");
|
||||
verify(processTaskAddSignRecordMapper, never()).insert(any(ProcessTaskAddSignRecord.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void addSignRollsBackAuditWhenFlowableReportsConcurrentChange() {
|
||||
prepareTaskAndNode(null);
|
||||
prepareOriginalApprover();
|
||||
prepareTargetValidation(List.of(originalAssignment()), validUser(TARGET_USER_ID, TENANT_ID));
|
||||
prepareAuditInsert();
|
||||
when(runtimeService.addMultiInstanceExecution(anyString(), anyString(), anyMap()))
|
||||
.thenThrow(new FlowableOptimisticLockingException("conflict"));
|
||||
RecordingTransactionManager transactionManager = new RecordingTransactionManager();
|
||||
|
||||
R result = transactionalService(transactionManager)
|
||||
.addSign(request(List.of(TARGET_USER_ID), "需要共同确认"));
|
||||
|
||||
assertThat(result.getCode()).isEqualTo(1);
|
||||
assertThat(result.getMsg()).isEqualTo("节点状态已变化,请刷新后重试");
|
||||
assertThat(transactionManager.rolledBack).isTrue();
|
||||
assertThat(transactionManager.committed).isFalse();
|
||||
verify(processTaskAddSignRecordMapper).insert(any(ProcessTaskAddSignRecord.class));
|
||||
verify(processTaskAddSignRecordMapper, never()).updateById(any(ProcessTaskAddSignRecord.class));
|
||||
}
|
||||
|
||||
private void prepareTaskAndNode(Task taskCreatedAfterAddSign) {
|
||||
when(taskService.createTaskQuery()).thenReturn(taskQuery);
|
||||
if (taskCreatedAfterAddSign == null) {
|
||||
when(taskQuery.singleResult()).thenReturn(sourceTask);
|
||||
}
|
||||
else {
|
||||
when(taskQuery.singleResult()).thenReturn(sourceTask, taskCreatedAfterAddSign);
|
||||
}
|
||||
when(sourceTask.getProcessInstanceId()).thenReturn(PROCESS_INSTANCE_ID);
|
||||
when(sourceTask.getTaskDefinitionKey()).thenReturn(NODE_ID);
|
||||
when(sourceTask.getProcessDefinitionId()).thenReturn(PROCESS_DEFINITION_ID);
|
||||
if (taskCreatedAfterAddSign != null) {
|
||||
when(taskCreatedAfterAddSign.getId()).thenReturn(ADDED_TASK_ID);
|
||||
}
|
||||
|
||||
ProcessNodeRecord nodeRecord = new ProcessNodeRecord().setId(NODE_RECORD_ID);
|
||||
when(processNodeRecordMapper.selectActiveByIdForUpdate(NODE_RECORD_ID, PROCESS_INSTANCE_ID, NODE_ID,
|
||||
TENANT_ID))
|
||||
.thenReturn(nodeRecord);
|
||||
Node node = new Node();
|
||||
node.setAssignedType(ProcessInstanceConstant.AssignedTypeClass.ROLE);
|
||||
node.setMultipleMode(ProcessInstanceConstant.MULTIPLE_MODE_AL_SAME);
|
||||
node.setAllowAddSign(true);
|
||||
when(nodeDataService.getNodeData(FLOW_ID, NODE_ID)).thenReturn(R.ok(node));
|
||||
}
|
||||
|
||||
private void prepareOriginalApprover() {
|
||||
prepareActiveAssignment();
|
||||
when(sourceTask.getAssignee()).thenReturn(String.valueOf(USER_ID));
|
||||
when(processInstanceRecordService.lambdaQuery())
|
||||
.thenAnswer(invocation -> new LambdaQueryChainWrapper<>(processInstanceBaseMapper));
|
||||
}
|
||||
|
||||
private void prepareActiveAssignment() {
|
||||
when(sourceTask.getId()).thenReturn(TASK_ID);
|
||||
when(processNodeRecordAssignUserService.lambdaQuery())
|
||||
.thenAnswer(invocation -> new LambdaQueryChainWrapper<>(assignmentBaseMapper));
|
||||
when(assignmentBaseMapper.selectOne(any())).thenReturn(originalAssignment());
|
||||
}
|
||||
|
||||
private void prepareTargetValidation(List<ProcessNodeRecordAssignUser> participants, SysUser targetUser) {
|
||||
when(assignmentBaseMapper.selectList(any())).thenReturn(participants);
|
||||
when(remoteUserService.getUserById(List.of(TARGET_USER_ID))).thenReturn(R.ok(List.of(targetUser)));
|
||||
}
|
||||
|
||||
private void prepareAuditInsert() {
|
||||
when(processTaskAddSignRecordMapper.insert(any(ProcessTaskAddSignRecord.class))).thenAnswer(invocation -> {
|
||||
ProcessTaskAddSignRecord record = invocation.getArgument(0);
|
||||
record.setId(ADD_SIGN_RECORD_ID);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
private ProcessNodeRecordAssignUser originalAssignment() {
|
||||
return new ProcessNodeRecordAssignUser()
|
||||
.setNodeRecordId(NODE_RECORD_ID)
|
||||
.setTaskId(TASK_ID)
|
||||
.setUserId(USER_ID)
|
||||
.setInitialUserId(USER_ID)
|
||||
.setAssignmentOrigin(ProcessInstanceConstant.ASSIGNMENT_ORIGIN_ORIGINAL)
|
||||
.setStatus(NodeStatusEnum.JXZ.getCode());
|
||||
}
|
||||
|
||||
private SysUser validUser(long userId, long tenantId) {
|
||||
SysUser user = new SysUser();
|
||||
user.setUserId(userId);
|
||||
user.setUsername("target");
|
||||
user.setName("目标审批人");
|
||||
user.setTenantId(tenantId);
|
||||
user.setDelFlag("0");
|
||||
user.setLockFlag("0");
|
||||
return user;
|
||||
}
|
||||
|
||||
private ITaskService transactionalService(RecordingTransactionManager transactionManager) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(taskServiceImpl);
|
||||
proxyFactory.addInterface(ITaskService.class);
|
||||
proxyFactory.addAdvice(new TransactionInterceptor(transactionManager,
|
||||
new AnnotationTransactionAttributeSource()));
|
||||
return (ITaskService) proxyFactory.getProxy();
|
||||
}
|
||||
|
||||
private AddSignTaskDto request(List<Long> userIds, String reason) {
|
||||
AddSignTaskDto request = new AddSignTaskDto();
|
||||
request.setTaskId(TASK_ID);
|
||||
request.setTargetUserIdList(userIds);
|
||||
request.setReason(reason);
|
||||
return request;
|
||||
}
|
||||
|
||||
private static final class RecordingTransactionManager extends AbstractPlatformTransactionManager {
|
||||
|
||||
private boolean committed;
|
||||
|
||||
private boolean rolledBack;
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) {
|
||||
committed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) {
|
||||
rolledBack = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package com.pig4cloud.pigx.flow.support.node;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.flow.constant.ProcessInstanceConstant;
|
||||
import com.pig4cloud.pigx.flow.dto.Node;
|
||||
import com.pig4cloud.pigx.flow.service.IProcessNodeDataService;
|
||||
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MultiInstanceHandlerTests {
|
||||
|
||||
@Test
|
||||
void countersignWaitsForDynamicallyExpandedInstanceCount() {
|
||||
IProcessNodeDataService nodeDataService = mock(IProcessNodeDataService.class);
|
||||
Node node = new Node();
|
||||
node.setMultipleMode(ProcessInstanceConstant.MULTIPLE_MODE_AL_SAME);
|
||||
when(nodeDataService.getNodeData("flow-1", "approve-1")).thenReturn(R.ok(node));
|
||||
MultiInstanceHandler handler = new MultiInstanceHandler(nodeDataService, Collections.emptyMap(),
|
||||
new ObjectMapper());
|
||||
ExecutionEntityImpl execution = mock(ExecutionEntityImpl.class);
|
||||
when(execution.getProcessDefinitionKey()).thenReturn("flow-1");
|
||||
when(execution.getCurrentActivityId()).thenReturn("approve-1");
|
||||
when(execution.getVariable("approve-1_approve_condition")).thenReturn(true);
|
||||
when(execution.getVariable("nrOfInstances")).thenReturn(3);
|
||||
when(execution.getVariable("nrOfCompletedInstances")).thenReturn(2);
|
||||
|
||||
assertThat(handler.completionCondition(execution)).isFalse();
|
||||
|
||||
when(execution.getVariable("nrOfCompletedInstances")).thenReturn(3);
|
||||
assertThat(handler.completionCondition(execution)).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
+2
-1
@@ -36,10 +36,11 @@
|
||||
<module>pigx-codegen</module>
|
||||
<module>pigx-daemon-elastic-job</module>
|
||||
<module>pigx-daemon-quartz</module>
|
||||
<module>pigx-jimu-platform</module>
|
||||
<module>pigx-pay-platform</module>
|
||||
<module>pigx-monitor</module>
|
||||
<module>pigx-mp-platform</module>
|
||||
<module>pigx-xxl-job-admin</module>
|
||||
<!-- JimuReport 启用说明:https://ourl.cn/R7bKJ8 -->
|
||||
<!--<module>pigx-jimu-platform</module>-->
|
||||
</modules>
|
||||
</project>
|
||||
Reference in new issue
Block a user