增加工作流代码可正常启动

This commit is contained in:
戚辰先生 2024-12-05 10:31:42 +08:00
parent 2c39b79515
commit bdbd4528a5
4 changed files with 0 additions and 762 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}