Back to Repositories

Validating Task Assignment Strategy Implementation in ruoyi-vue-pro

A comprehensive unit test suite for the BpmTaskCandidateAssignEmptyStrategy class, validating the empty task assignment handling in the RuoYi Vue Pro workflow system.

Test Coverage Overview

The test suite provides thorough coverage of the empty task assignment strategy implementation.

  • Tests user calculation logic for both task-based and activity-based scenarios
  • Validates different assignment handler types (ASSIGN_USER, ASSIGN_ADMIN)
  • Covers process definition and flow element interactions
  • Verifies manager user ID handling

Implementation Analysis

The testing approach utilizes Mockito for dependency isolation and behavior verification.

  • Employs MockedStatic for utility class mocking
  • Implements BaseMockitoUnitTest for consistent test setup
  • Uses mock objects to simulate Flowable engine components
  • Validates business logic through assertion checks

Technical Details

  • JUnit Jupiter test framework
  • Mockito mocking framework
  • Flowable BPM engine integration
  • Custom utility classes for BPMN model handling
  • Randomized test data generation

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices for workflow component validation.

  • Proper test isolation using mocks
  • Comprehensive scenario coverage
  • Clear test method organization
  • Effective use of test utilities
  • Robust assertion patterns

yunaiv/ruoyi-vue-pro

yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateAssignEmptyStrategyTest.java

            
package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.other;

import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmUserTaskAssignEmptyHandlerTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;

import java.util.Set;

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.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

public class BpmTaskCandidateAssignEmptyStrategyTest extends BaseMockitoUnitTest {

    @InjectMocks
    private BpmTaskCandidateAssignEmptyStrategy strategy;

    @Mock
    private BpmProcessDefinitionService processDefinitionService;

    @Test
    public void testCalculateUsersByTask() {
        try (MockedStatic<FlowableUtils> flowableUtilMockedStatic = mockStatic(FlowableUtils.class);
             MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
            // 准备参数
            DelegateExecution execution = mock(DelegateExecution.class);
            String param = randomString();
            // mock 方法(execution)
            String processDefinitionId = randomString();
            when(execution.getProcessDefinitionId()).thenReturn(processDefinitionId);
            FlowElement flowElement = mock(FlowElement.class);
            when(execution.getCurrentFlowElement()).thenReturn(flowElement);
            // mock 方法(parseAssignEmptyHandlerType)
            bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
                    .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_USER.getType());
            bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerUserIds(same(flowElement)))
                    .thenReturn(ListUtil.of(1L, 2L));

            // 调用
            Set<Long> userIds = strategy.calculateUsersByTask(execution, param);
            // 断言
            assertEquals(SetUtils.asSet(1L, 2L), userIds);
        }

    }

    @Test
    public void testCalculateUsersByActivity() {
        try (MockedStatic<BpmnModelUtils> bpmnModelUtilsMockedStatic = mockStatic(BpmnModelUtils.class)) {
            // 准备参数
            String processDefinitionId = randomString();
            String activityId = randomString();
            String param = randomString();
            // mock 方法(getFlowElementById)
            FlowElement flowElement = mock(FlowElement.class);
            BpmnModel bpmnModel = mock(BpmnModel.class);
            bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.getFlowElementById(same(bpmnModel), eq(activityId)))
                    .thenReturn(flowElement);
            // mock 方法(parseAssignEmptyHandlerType)
            bpmnModelUtilsMockedStatic.when(() -> BpmnModelUtils.parseAssignEmptyHandlerType(same(flowElement)))
                 .thenReturn(BpmUserTaskAssignEmptyHandlerTypeEnum.ASSIGN_ADMIN.getType());
            // mock 方法(getProcessDefinitionInfo)
            BpmProcessDefinitionInfoDO processDefinition = randomPojo(BpmProcessDefinitionInfoDO.class,
                    o -> o.setManagerUserIds(ListUtil.of(1L, 2L)));
            when(processDefinitionService.getProcessDefinitionInfo(eq(processDefinitionId))).thenReturn(processDefinition);

            // 调用
            Set<Long> userIds = strategy.calculateUsersByActivity(bpmnModel, activityId, param,
                    null, processDefinitionId, null);
            // 断言
            assertEquals(SetUtils.asSet(1L, 2L), userIds);
        }
    }

}