增加工作流代码可正常启动
This commit is contained in:
parent
2c39b79515
commit
bdbd4528a5
@ -1,325 +0,0 @@
|
||||
package com.qqchen.deploy.backend.workflow.engine;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
|
||||
import com.qqchen.deploy.backend.workflow.engine.context.DefaultWorkflowContext;
|
||||
import com.qqchen.deploy.backend.workflow.engine.executor.*;
|
||||
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
|
||||
import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum;
|
||||
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
|
||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnum;
|
||||
import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository;
|
||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository;
|
||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService;
|
||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowLogService;
|
||||
import com.qqchen.deploy.backend.workflow.service.IWorkflowVariableService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootTest(classes = {
|
||||
WorkflowEngineTest.TestConfig.class,
|
||||
DefaultWorkflowEngine.class,
|
||||
ObjectMapper.class
|
||||
})
|
||||
class WorkflowEngineTest {
|
||||
|
||||
@Configuration
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
Map<NodeTypeEnum, NodeExecutor> nodeExecutors() {
|
||||
Map<NodeTypeEnum, NodeExecutor> executors = new HashMap<>();
|
||||
StartNodeExecutor startExecutor = mock(StartNodeExecutor.class);
|
||||
doNothing().when(startExecutor).execute(any(), any());
|
||||
|
||||
EndNodeExecutor endExecutor = mock(EndNodeExecutor.class);
|
||||
doNothing().when(endExecutor).execute(any(), any());
|
||||
|
||||
TaskNodeExecutor taskExecutor = mock(TaskNodeExecutor.class);
|
||||
doNothing().when(taskExecutor).execute(any(), any());
|
||||
|
||||
GatewayNodeExecutor gatewayExecutor = mock(GatewayNodeExecutor.class);
|
||||
doNothing().when(gatewayExecutor).execute(any(), any());
|
||||
|
||||
executors.put(NodeTypeEnum.START, startExecutor);
|
||||
executors.put(NodeTypeEnum.END, endExecutor);
|
||||
executors.put(NodeTypeEnum.TASK, taskExecutor);
|
||||
executors.put(NodeTypeEnum.GATEWAY, gatewayExecutor);
|
||||
return executors;
|
||||
}
|
||||
|
||||
@Bean
|
||||
IWorkflowVariableService workflowVariableService() {
|
||||
IWorkflowVariableService service = mock(IWorkflowVariableService.class);
|
||||
doNothing().when(service).setVariable(any(), anyString(), any());
|
||||
return service;
|
||||
}
|
||||
|
||||
@Bean
|
||||
IWorkflowLogService workflowLogService() {
|
||||
return mock(IWorkflowLogService.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
DefaultWorkflowContext.Factory workflowContextFactory(
|
||||
IWorkflowVariableService variableService,
|
||||
IWorkflowLogService logService
|
||||
) {
|
||||
return new DefaultWorkflowContext.Factory(variableService, logService);
|
||||
}
|
||||
}
|
||||
|
||||
@Resource
|
||||
private WorkflowEngine workflowEngine;
|
||||
|
||||
@MockBean
|
||||
private IWorkflowDefinitionService workflowDefinitionService;
|
||||
|
||||
@MockBean
|
||||
private IWorkflowDefinitionRepository workflowDefinitionRepository;
|
||||
|
||||
@MockBean
|
||||
private IWorkflowInstanceRepository workflowInstanceRepository;
|
||||
|
||||
@MockBean
|
||||
private INodeInstanceRepository nodeInstanceRepository;
|
||||
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private NodeInstance savedStartNode;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
log.info("Setting up workflow engine test mocks...");
|
||||
|
||||
// Mock workflowDefinitionService
|
||||
when(workflowDefinitionService.create(any())).thenAnswer(i -> {
|
||||
WorkflowDefinitionDTO dto = i.getArgument(0);
|
||||
dto.setId(1L);
|
||||
log.info("Created workflow definition with ID: {}", dto.getId());
|
||||
return dto;
|
||||
});
|
||||
|
||||
// Mock workflowDefinitionRepository
|
||||
when(workflowDefinitionRepository.findByCodeAndDeletedFalse(anyString()))
|
||||
.thenAnswer(i -> {
|
||||
WorkflowDefinition definition = new WorkflowDefinition();
|
||||
definition.setId(1L);
|
||||
definition.setName("简单测试工作流");
|
||||
definition.setCode("SIMPLE_TEST_WORKFLOW");
|
||||
definition.setStatus(WorkflowStatusEnum.PUBLISHED);
|
||||
definition.setNodeConfig(createSimpleWorkflow().getNodeConfig());
|
||||
definition.setTransitionConfig(createSimpleWorkflow().getTransitionConfig());
|
||||
log.info("Found workflow definition: code={}, status={}", definition.getCode(), definition.getStatus());
|
||||
return definition;
|
||||
});
|
||||
|
||||
// Mock workflowInstanceRepository
|
||||
when(workflowInstanceRepository.save(any())).thenAnswer(i -> {
|
||||
WorkflowInstance instance = i.getArgument(0);
|
||||
if (instance.getId() == null) {
|
||||
instance.setId(1L);
|
||||
}
|
||||
log.info("Saved workflow instance: id={}, status={}", instance.getId(), instance.getStatus());
|
||||
return instance;
|
||||
});
|
||||
|
||||
// Mock nodeInstanceRepository
|
||||
when(nodeInstanceRepository.save(any())).thenAnswer(i -> {
|
||||
NodeInstance node = i.getArgument(0);
|
||||
if (node.getId() == null) {
|
||||
node.setId(System.nanoTime());
|
||||
}
|
||||
savedStartNode = node;
|
||||
|
||||
// Create and set the workflow instance if it doesn't exist
|
||||
if (node.getWorkflowInstance() == null) {
|
||||
WorkflowInstance instance = new WorkflowInstance();
|
||||
instance.setId(1L);
|
||||
instance.setStatus(WorkflowStatusEnum.RUNNING);
|
||||
node.setWorkflowInstance(instance);
|
||||
}
|
||||
|
||||
log.info("Saved node instance: id={}, type={}, status={}, workflowInstanceId={}",
|
||||
node.getId(), node.getNodeType(), node.getStatus(), node.getWorkflowInstance().getId());
|
||||
return node;
|
||||
});
|
||||
|
||||
when(nodeInstanceRepository.findById(any())).thenAnswer(i -> {
|
||||
if (savedStartNode != null && savedStartNode.getId().equals(i.getArgument(0))) {
|
||||
log.info("Found node instance by id: {}, type={}, status={}",
|
||||
savedStartNode.getId(), savedStartNode.getNodeType(), savedStartNode.getStatus());
|
||||
return Optional.of(savedStartNode);
|
||||
}
|
||||
log.warn("Node instance not found with id: {}", (Object)i.getArgument(0));
|
||||
return Optional.empty();
|
||||
});
|
||||
|
||||
when(nodeInstanceRepository.findByWorkflowInstanceIdOrderByCreateTime(any()))
|
||||
.thenAnswer(i -> {
|
||||
WorkflowInstance instance = new WorkflowInstance();
|
||||
instance.setId(1L);
|
||||
instance.setStatus(WorkflowStatusEnum.RUNNING);
|
||||
|
||||
List<NodeInstance> nodes = List.of(
|
||||
createNodeInstance(NodeTypeEnum.START, NodeStatusEnum.COMPLETED),
|
||||
createNodeInstance(NodeTypeEnum.TASK, NodeStatusEnum.COMPLETED),
|
||||
createNodeInstance(NodeTypeEnum.END, NodeStatusEnum.COMPLETED)
|
||||
);
|
||||
|
||||
// Set workflow instance for each node
|
||||
nodes.forEach(node -> node.setWorkflowInstance(instance));
|
||||
|
||||
log.info("Found {} nodes for workflow instance id={}", nodes.size(), i.getArgument(0));
|
||||
nodes.forEach(node -> log.info("Node: type={}, status={}", node.getNodeType(), node.getStatus()));
|
||||
|
||||
return nodes;
|
||||
});
|
||||
|
||||
log.info("Test setup completed");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleWorkflow() {
|
||||
log.info("Starting simple workflow test");
|
||||
|
||||
// 1. 创建工作流定义
|
||||
WorkflowDefinitionDTO definition = createSimpleWorkflow();
|
||||
log.info("Created workflow definition: name={}, code={}", definition.getName(), definition.getCode());
|
||||
|
||||
// 2. 启动工作流实例
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put("input", "test");
|
||||
log.info("Starting workflow with variables: {}", variables);
|
||||
|
||||
WorkflowInstance instance = workflowEngine.startWorkflow(
|
||||
definition.getCode(),
|
||||
"TEST-" + System.currentTimeMillis(),
|
||||
variables
|
||||
);
|
||||
|
||||
// 3. 验证工作流实例状态
|
||||
assertNotNull(instance);
|
||||
assertEquals(WorkflowStatusEnum.RUNNING, instance.getStatus());
|
||||
log.info("Workflow instance started: id={}, status={}", instance.getId(), instance.getStatus());
|
||||
|
||||
// 4. 验证节点执行状态
|
||||
List<NodeInstance> nodes = nodeInstanceRepository.findByWorkflowInstanceIdOrderByCreateTime(instance.getId());
|
||||
assertEquals(3, nodes.size());
|
||||
log.info("Found {} nodes in workflow instance", nodes.size());
|
||||
|
||||
// 验证开始节点
|
||||
NodeInstance startNode = nodes.get(0);
|
||||
assertEquals(NodeTypeEnum.START, startNode.getNodeType());
|
||||
assertEquals(NodeStatusEnum.COMPLETED, startNode.getStatus());
|
||||
log.info("Start node validation passed: id={}, status={}", startNode.getId(), startNode.getStatus());
|
||||
|
||||
// 验证Shell节点
|
||||
NodeInstance shellNode = nodes.get(1);
|
||||
assertEquals(NodeTypeEnum.TASK, shellNode.getNodeType());
|
||||
assertEquals(NodeStatusEnum.COMPLETED, shellNode.getStatus());
|
||||
log.info("Shell node validation passed: id={}, status={}", shellNode.getId(), shellNode.getStatus());
|
||||
|
||||
// 验证结束节点
|
||||
NodeInstance endNode = nodes.get(2);
|
||||
assertEquals(NodeTypeEnum.END, endNode.getNodeType());
|
||||
assertEquals(NodeStatusEnum.COMPLETED, endNode.getStatus());
|
||||
log.info("End node validation passed: id={}, status={}", endNode.getId(), endNode.getStatus());
|
||||
|
||||
log.info("Simple workflow test completed successfully");
|
||||
}
|
||||
|
||||
private WorkflowDefinitionDTO createSimpleWorkflow() {
|
||||
WorkflowDefinitionDTO dto = new WorkflowDefinitionDTO();
|
||||
dto.setId(1L);
|
||||
dto.setName("简单测试工作流");
|
||||
dto.setCode("SIMPLE_TEST_WORKFLOW");
|
||||
dto.setStatus(WorkflowStatusEnum.PUBLISHED);
|
||||
|
||||
// 节点配置
|
||||
String nodeConfig = """
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "start",
|
||||
"name": "开始",
|
||||
"type": "START"
|
||||
},
|
||||
{
|
||||
"id": "shell",
|
||||
"name": "Shell任务",
|
||||
"type": "TASK",
|
||||
"config": {
|
||||
"type": "SHELL",
|
||||
"script": "echo 'Hello World'",
|
||||
"workingDirectory": "/tmp",
|
||||
"successExitCode": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "end",
|
||||
"name": "结束",
|
||||
"type": "END"
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
dto.setNodeConfig(nodeConfig);
|
||||
|
||||
// 流转配置
|
||||
String transitionConfig = """
|
||||
[
|
||||
{
|
||||
"sourceNodeId": "start",
|
||||
"targetNodeId": "shell",
|
||||
"condition": null,
|
||||
"priority": 1
|
||||
},
|
||||
{
|
||||
"sourceNodeId": "shell",
|
||||
"targetNodeId": "end",
|
||||
"condition": null,
|
||||
"priority": 1
|
||||
}
|
||||
]
|
||||
""";
|
||||
dto.setTransitionConfig(transitionConfig);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private NodeInstance createNodeInstance(NodeTypeEnum type, NodeStatusEnum status) {
|
||||
NodeInstance node = new NodeInstance();
|
||||
node.setId(System.nanoTime());
|
||||
node.setNodeType(type);
|
||||
node.setStatus(status);
|
||||
|
||||
// Create and set a workflow instance
|
||||
WorkflowInstance instance = new WorkflowInstance();
|
||||
instance.setId(1L);
|
||||
instance.setStatus(WorkflowStatusEnum.RUNNING);
|
||||
node.setWorkflowInstance(instance);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@ -1,138 +0,0 @@
|
||||
package com.qqchen.deploy.backend.workflow.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.entity.NodeDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
|
||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@ActiveProfiles("test")
|
||||
class NodeDefinitionRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
private INodeDefinitionRepository nodeDefinitionRepository;
|
||||
|
||||
@Autowired
|
||||
private IWorkflowDefinitionRepository workflowDefinitionRepository;
|
||||
|
||||
private WorkflowDefinition workflowDefinition;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// 创建工作流定义
|
||||
workflowDefinition = new WorkflowDefinition();
|
||||
workflowDefinition.setCode("TEST-WF");
|
||||
workflowDefinition.setName("Test Workflow");
|
||||
workflowDefinition.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
workflowDefinition.setVersion(1);
|
||||
workflowDefinition.setEnabled(true);
|
||||
workflowDefinition = workflowDefinitionRepository.save(workflowDefinition);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByWorkflowDefinitionId_ShouldReturnNodesOrderedByOrderNum() {
|
||||
// Given
|
||||
NodeDefinition node1 = createNodeDefinition("NODE-001", "Node 1", NodeTypeEnum.START, 1);
|
||||
NodeDefinition node2 = createNodeDefinition("NODE-002", "Node 2", NodeTypeEnum.TASK, 2);
|
||||
NodeDefinition node3 = createNodeDefinition("NODE-003", "Node 3", NodeTypeEnum.END, 3);
|
||||
|
||||
nodeDefinitionRepository.save(node1);
|
||||
nodeDefinitionRepository.save(node2);
|
||||
nodeDefinitionRepository.save(node3);
|
||||
|
||||
// When
|
||||
List<NodeDefinition> results = nodeDefinitionRepository.findByWorkflowDefinitionId(workflowDefinition.getId());
|
||||
|
||||
// Then
|
||||
assertThat(results).hasSize(3);
|
||||
assertThat(results.get(0).getOrderNum()).isEqualTo(1);
|
||||
assertThat(results.get(1).getOrderNum()).isEqualTo(2);
|
||||
assertThat(results.get(2).getOrderNum()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByWorkflowDefinitionIdAndType_ShouldReturnNodesWithSpecificType() {
|
||||
// Given
|
||||
NodeDefinition startNode = createNodeDefinition("START-001", "Start Node", NodeTypeEnum.START, 1);
|
||||
NodeDefinition taskNode1 = createNodeDefinition("TASK-001", "Task Node 1", NodeTypeEnum.TASK, 2);
|
||||
NodeDefinition taskNode2 = createNodeDefinition("TASK-002", "Task Node 2", NodeTypeEnum.TASK, 3);
|
||||
NodeDefinition endNode = createNodeDefinition("END-001", "End Node", NodeTypeEnum.END, 4);
|
||||
|
||||
nodeDefinitionRepository.save(startNode);
|
||||
nodeDefinitionRepository.save(taskNode1);
|
||||
nodeDefinitionRepository.save(taskNode2);
|
||||
nodeDefinitionRepository.save(endNode);
|
||||
|
||||
// When
|
||||
List<NodeDefinition> results = nodeDefinitionRepository.findByWorkflowDefinitionIdAndType(
|
||||
workflowDefinition.getId(), NodeTypeEnum.TASK);
|
||||
|
||||
// Then
|
||||
assertThat(results).hasSize(2);
|
||||
assertThat(results).allMatch(node -> node.getType() == NodeTypeEnum.TASK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByWorkflowDefinitionIdAndCode_ShouldReturnSpecificNode() {
|
||||
// Given
|
||||
NodeDefinition node = createNodeDefinition("NODE-001", "Test Node", NodeTypeEnum.TASK, 1);
|
||||
nodeDefinitionRepository.save(node);
|
||||
|
||||
// When
|
||||
NodeDefinition result = nodeDefinitionRepository.findByWorkflowDefinitionIdAndCodeAndDeletedFalse(
|
||||
workflowDefinition.getId(), "NODE-001");
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getCode()).isEqualTo("NODE-001");
|
||||
}
|
||||
|
||||
@Test
|
||||
void existsByWorkflowDefinitionIdAndCode_ShouldReturnTrue_WhenNodeExists() {
|
||||
// Given
|
||||
NodeDefinition node = createNodeDefinition("NODE-001", "Test Node", NodeTypeEnum.TASK, 1);
|
||||
nodeDefinitionRepository.save(node);
|
||||
|
||||
// When
|
||||
boolean exists = nodeDefinitionRepository.existsByWorkflowDefinitionIdAndCodeAndDeletedFalse(
|
||||
workflowDefinition.getId(), "NODE-001");
|
||||
|
||||
// Then
|
||||
assertThat(exists).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteByWorkflowDefinitionId_ShouldMarkNodesAsDeleted() {
|
||||
// Given
|
||||
NodeDefinition node1 = createNodeDefinition("NODE-001", "Node 1", NodeTypeEnum.START, 1);
|
||||
NodeDefinition node2 = createNodeDefinition("NODE-002", "Node 2", NodeTypeEnum.TASK, 2);
|
||||
nodeDefinitionRepository.save(node1);
|
||||
nodeDefinitionRepository.save(node2);
|
||||
|
||||
// When
|
||||
nodeDefinitionRepository.deleteByWorkflowDefinitionId(workflowDefinition.getId());
|
||||
|
||||
// Then
|
||||
List<NodeDefinition> remainingNodes = nodeDefinitionRepository.findByWorkflowDefinitionId(workflowDefinition.getId());
|
||||
assertThat(remainingNodes).isEmpty();
|
||||
}
|
||||
|
||||
private NodeDefinition createNodeDefinition(String code, String name, NodeTypeEnum type, Integer orderNum) {
|
||||
NodeDefinition node = new NodeDefinition();
|
||||
node.setCode(code);
|
||||
node.setName(name);
|
||||
node.setType(type);
|
||||
node.setOrderNum(orderNum);
|
||||
node.setWorkflowDefinition(workflowDefinition);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
package com.qqchen.deploy.backend.workflow.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnum;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
@ActiveProfiles("test")
|
||||
class WorkflowDefinitionRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
private IWorkflowDefinitionRepository workflowDefinitionRepository;
|
||||
|
||||
@Test
|
||||
void findLatestByCode_ShouldReturnLatestVersion() {
|
||||
// Given
|
||||
WorkflowDefinition def1 = createWorkflowDefinition("TEST-001", "Test Workflow 1", 1);
|
||||
WorkflowDefinition def2 = createWorkflowDefinition("TEST-001", "Test Workflow 1", 2);
|
||||
workflowDefinitionRepository.save(def1);
|
||||
workflowDefinitionRepository.save(def2);
|
||||
|
||||
// When
|
||||
Optional<WorkflowDefinition> result = workflowDefinitionRepository.findLatestByCode("TEST-001");
|
||||
|
||||
// Then
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get().getVersion()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByCodeAndVersion_ShouldReturnSpecificVersion() {
|
||||
// Given
|
||||
WorkflowDefinition def1 = createWorkflowDefinition("TEST-002", "Test Workflow 2", 1);
|
||||
WorkflowDefinition def2 = createWorkflowDefinition("TEST-002", "Test Workflow 2", 2);
|
||||
workflowDefinitionRepository.save(def1);
|
||||
workflowDefinitionRepository.save(def2);
|
||||
|
||||
// When
|
||||
Optional<WorkflowDefinition> result = workflowDefinitionRepository.findByCodeAndVersionAndDeletedFalse("TEST-002", 1);
|
||||
|
||||
// Then
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get().getVersion()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAllVersionsByCode_ShouldReturnAllVersionsOrderedByVersionDesc() {
|
||||
// Given
|
||||
WorkflowDefinition def1 = createWorkflowDefinition("TEST-003", "Test Workflow 3", 1);
|
||||
WorkflowDefinition def2 = createWorkflowDefinition("TEST-003", "Test Workflow 3", 2);
|
||||
WorkflowDefinition def3 = createWorkflowDefinition("TEST-003", "Test Workflow 3", 3);
|
||||
workflowDefinitionRepository.save(def1);
|
||||
workflowDefinitionRepository.save(def2);
|
||||
workflowDefinitionRepository.save(def3);
|
||||
|
||||
// When
|
||||
List<WorkflowDefinition> results = workflowDefinitionRepository.findAllVersionsByCode("TEST-003");
|
||||
|
||||
// Then
|
||||
assertThat(results).hasSize(3);
|
||||
assertThat(results.get(0).getVersion()).isEqualTo(3);
|
||||
assertThat(results.get(1).getVersion()).isEqualTo(2);
|
||||
assertThat(results.get(2).getVersion()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByStatus_ShouldReturnWorkflowsWithSpecificStatus() {
|
||||
// Given
|
||||
WorkflowDefinition def1 = createWorkflowDefinition("TEST-004", "Test Workflow 4", 1);
|
||||
def1.setStatus(WorkflowStatusEnum.PUBLISHED);
|
||||
WorkflowDefinition def2 = createWorkflowDefinition("TEST-005", "Test Workflow 5", 1);
|
||||
def2.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
workflowDefinitionRepository.save(def1);
|
||||
workflowDefinitionRepository.save(def2);
|
||||
|
||||
// When
|
||||
List<WorkflowDefinition> results = workflowDefinitionRepository.findByStatusAndDeletedFalse(WorkflowStatusEnum.PUBLISHED);
|
||||
|
||||
// Then
|
||||
assertThat(results).hasSize(1);
|
||||
assertThat(results.get(0).getStatus()).isEqualTo(WorkflowStatusEnum.PUBLISHED);
|
||||
}
|
||||
|
||||
@Test
|
||||
void existsByCode_ShouldReturnTrueWhenCodeExists() {
|
||||
// Given
|
||||
WorkflowDefinition def = createWorkflowDefinition("TEST-006", "Test Workflow 6", 1);
|
||||
workflowDefinitionRepository.save(def);
|
||||
|
||||
// When
|
||||
boolean exists = workflowDefinitionRepository.existsByCodeAndDeletedFalse("TEST-006");
|
||||
|
||||
// Then
|
||||
assertThat(exists).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findLatestVersionByCode_ShouldReturnHighestVersion() {
|
||||
// Given
|
||||
WorkflowDefinition def1 = createWorkflowDefinition("TEST-007", "Test Workflow 7", 1);
|
||||
WorkflowDefinition def2 = createWorkflowDefinition("TEST-007", "Test Workflow 7", 2);
|
||||
WorkflowDefinition def3 = createWorkflowDefinition("TEST-007", "Test Workflow 7", 3);
|
||||
workflowDefinitionRepository.save(def1);
|
||||
workflowDefinitionRepository.save(def2);
|
||||
workflowDefinitionRepository.save(def3);
|
||||
|
||||
// When
|
||||
Integer latestVersion = workflowDefinitionRepository.findLatestVersionByCode("TEST-007");
|
||||
|
||||
// Then
|
||||
assertThat(latestVersion).isEqualTo(3);
|
||||
}
|
||||
|
||||
private WorkflowDefinition createWorkflowDefinition(String code, String name, Integer version) {
|
||||
WorkflowDefinition def = new WorkflowDefinition();
|
||||
def.setCode(code);
|
||||
def.setName(name);
|
||||
def.setVersion(version);
|
||||
def.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
def.setEnabled(true);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
package com.qqchen.deploy.backend.workflow.service;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.workflow.converter.WorkflowDefinitionConverter;
|
||||
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
|
||||
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
|
||||
import com.qqchen.deploy.backend.workflow.enums.WorkflowStatusEnum;
|
||||
import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository;
|
||||
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
|
||||
import com.qqchen.deploy.backend.workflow.service.impl.WorkflowDefinitionServiceImpl;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class WorkflowDefinitionServiceTest {
|
||||
|
||||
@Mock
|
||||
private IWorkflowDefinitionRepository workflowDefinitionRepository;
|
||||
|
||||
@Mock
|
||||
private INodeDefinitionRepository nodeDefinitionRepository;
|
||||
|
||||
@Mock
|
||||
private WorkflowDefinitionConverter workflowDefinitionConverter;
|
||||
|
||||
@InjectMocks
|
||||
private WorkflowDefinitionServiceImpl workflowDefinitionService;
|
||||
|
||||
private WorkflowDefinition mockWorkflowDefinition;
|
||||
private WorkflowDefinitionDTO mockWorkflowDefinitionDTO;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mockWorkflowDefinition = new WorkflowDefinition();
|
||||
mockWorkflowDefinition.setId(1L);
|
||||
mockWorkflowDefinition.setCode("TEST-001");
|
||||
mockWorkflowDefinition.setName("Test Workflow");
|
||||
mockWorkflowDefinition.setVersion(1);
|
||||
mockWorkflowDefinition.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
mockWorkflowDefinition.setEnabled(true);
|
||||
|
||||
mockWorkflowDefinitionDTO = new WorkflowDefinitionDTO();
|
||||
mockWorkflowDefinitionDTO.setId(1L);
|
||||
mockWorkflowDefinitionDTO.setCode("TEST-001");
|
||||
mockWorkflowDefinitionDTO.setName("Test Workflow");
|
||||
mockWorkflowDefinitionDTO.setVersion(1);
|
||||
mockWorkflowDefinitionDTO.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
mockWorkflowDefinitionDTO.setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void create_ShouldCreateNewWorkflowDefinition() {
|
||||
// Given
|
||||
when(workflowDefinitionRepository.existsByCodeAndDeletedFalse(anyString())).thenReturn(false);
|
||||
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinition);
|
||||
when(workflowDefinitionConverter.toEntity(any(WorkflowDefinitionDTO.class))).thenReturn(mockWorkflowDefinition);
|
||||
when(workflowDefinitionConverter.toDto(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinitionDTO);
|
||||
|
||||
// When
|
||||
WorkflowDefinitionDTO result = workflowDefinitionService.create(mockWorkflowDefinitionDTO);
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getStatus()).isEqualTo(WorkflowStatusEnum.DRAFT);
|
||||
assertThat(result.getVersion()).isEqualTo(1);
|
||||
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void create_ShouldThrowException_WhenCodeExists() {
|
||||
// Given
|
||||
when(workflowDefinitionRepository.existsByCodeAndDeletedFalse(anyString())).thenReturn(true);
|
||||
|
||||
// When/Then
|
||||
assertThatThrownBy(() -> workflowDefinitionService.create(mockWorkflowDefinitionDTO))
|
||||
.isInstanceOf(BusinessException.class)
|
||||
.hasMessage("工作流编码已存在");
|
||||
}
|
||||
|
||||
@Test
|
||||
void publish_ShouldPublishWorkflowDefinition() {
|
||||
// Given
|
||||
mockWorkflowDefinition.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(mockWorkflowDefinition));
|
||||
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinition);
|
||||
when(workflowDefinitionConverter.toDto(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinitionDTO);
|
||||
|
||||
// When
|
||||
WorkflowDefinitionDTO result = workflowDefinitionService.publish(1L);
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getStatus()).isEqualTo(WorkflowStatusEnum.PUBLISHED);
|
||||
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void publish_ShouldThrowException_WhenNotDraft() {
|
||||
// Given
|
||||
mockWorkflowDefinition.setStatus(WorkflowStatusEnum.PUBLISHED);
|
||||
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(mockWorkflowDefinition));
|
||||
|
||||
// When/Then
|
||||
assertThatThrownBy(() -> workflowDefinitionService.publish(1L))
|
||||
.isInstanceOf(BusinessException.class)
|
||||
.hasMessage("只有草稿状态的工作流定义可以发布");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createNewVersion_ShouldCreateNewVersion() {
|
||||
// Given
|
||||
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(mockWorkflowDefinition));
|
||||
when(workflowDefinitionRepository.findLatestVersionByCode(anyString())).thenReturn(1);
|
||||
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinition);
|
||||
when(workflowDefinitionConverter.toDto(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinitionDTO);
|
||||
|
||||
// When
|
||||
WorkflowDefinitionDTO result = workflowDefinitionService.createNewVersion(1L);
|
||||
|
||||
// Then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getStatus()).isEqualTo(WorkflowStatusEnum.DRAFT);
|
||||
assertThat(result.getVersion()).isEqualTo(2);
|
||||
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAllVersions_ShouldReturnAllVersions() {
|
||||
// Given
|
||||
WorkflowDefinition version1 = createWorkflowDefinition(1);
|
||||
WorkflowDefinition version2 = createWorkflowDefinition(2);
|
||||
List<WorkflowDefinition> versions = Arrays.asList(version2, version1);
|
||||
|
||||
when(workflowDefinitionRepository.findAllVersionsByCode(anyString())).thenReturn(versions);
|
||||
when(workflowDefinitionConverter.toDto(any(WorkflowDefinition.class))).thenReturn(mockWorkflowDefinitionDTO);
|
||||
|
||||
// When
|
||||
List<WorkflowDefinitionDTO> results = workflowDefinitionService.findAllVersions("TEST-001");
|
||||
|
||||
// Then
|
||||
assertThat(results).hasSize(2);
|
||||
verify(workflowDefinitionRepository).findAllVersionsByCode("TEST-001");
|
||||
}
|
||||
|
||||
private WorkflowDefinition createWorkflowDefinition(int version) {
|
||||
WorkflowDefinition def = new WorkflowDefinition();
|
||||
def.setId((long) version);
|
||||
def.setCode("TEST-001");
|
||||
def.setName("Test Workflow");
|
||||
def.setVersion(version);
|
||||
def.setStatus(WorkflowStatusEnum.DRAFT);
|
||||
def.setEnabled(true);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user