BPMN文件的单元测试

1 unit-testing bpmn activiti

嗨,我们正在Activiti 6.0.0以及Spring Microservices上的Spring-Boot应用程序中使用。我必须在具有DelegateExpression的bpmn文件上编写单元测试。谁能为我指出一些关于UnitTest的想法?

Meh*_*ebi 6

我之前已经完成了一个经过全面测试的activiti项目。根据您的问题,我将其上传到我的github activiti-test上,因此您可以访问此答案的完整且可执行的源代码。该项目基于Maven,Activiti,Spring,H2和JUnit。但是如果您想通过Spring Boot运行它,那么您可以看到我的其他示例项目Spring-boot kickstart sample。活动测试项目结构:

  1. Maven项目POM.xml 您可以在IDE或任何您喜欢的地方将项目导入(激活测试)为现有的Maven项目。

重要的依赖关系是:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    .
    .
    .
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    .
    .
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    .
    .
    .
Run Code Online (Sandbox Code Playgroud)

2. applicationContext.xml

重要的代码块是启动activiti引擎(bean:processEngineConfiguration)

<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <!-- H2 -->
    <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000"  />
    <property name="driverClass" value="org.h2.Driver" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    <property name="databaseSchemaUpdate" value="true" /> <!-- important and valid values : true,false,create-drop -->
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="jobExecutorActivate" value="true" />
    <property name="asyncExecutorEnabled" value="true" />
    <property name="asyncExecutorActivate" value="true" />
</bean>
Run Code Online (Sandbox Code Playgroud)

3.创建活动数据库模式

在示例代码中,有一个名为InitDb的类bean 进行调用

org.activiti.engine.impl.db.DbSchemaCreate.main(null);
Run Code Online (Sandbox Code Playgroud)

4.准备测试环境

有一个名为BaseTest的类可简化其他测试:第一部分是activiti服务的实例,第二部分是一种通过下一个代码块中的BaseTest子类部署进程的方法。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(BaseTest.APPCONTEXT)
public abstract class BaseTest implements ApplicationContextAware {

    public static final String APPCONTEXT = "/applicationContext.xml";

    Logger logger = Logger.getLogger(BaseTest.class);
    public static ApplicationContext CONTEXT;

    @Autowired(required=true)
    protected ProcessDeployer processDeployer;

    @Autowired
    protected MyProcessEngine processEngine;

    protected RuntimeService runtimeService;
    protected TaskService taskService;
    protected RepositoryService repositoryService;
    protected HistoryService historyService;

    @PostConstruct  
    public void init() {
        runtimeService = processEngine.getProcessEngine().getRuntimeService();
        taskService = processEngine.getProcessEngine().getTaskService();
        repositoryService = processEngine.getProcessEngine().getRepositoryService();
        historyService = processEngine.getProcessEngine().getHistoryService();
    }
    .
    .
    .
    .
    private List<String> deploymentIds = new ArrayList<String>();
    @Before
    public void deploy()
    {
        if(deploymentIds.size() > 0)
            for(String deploymentId : deploymentIds)
                repositoryService.deleteDeployment(deploymentId);
        deploymentIds.clear();

        long beforeCount = processDeployer.getDeployedCount();
        logger.info("Number of Process Deployed Before start to deploy any new thing : " + beforeCount);
        if(getBpmnFiles() != null)
            for(String bpmn : getBpmnFiles())
            {           
                if(bpmn != null)
                    deploymentIds.add(processDeployer.deploy(bpmn));
            }
        logger.info(processDeployer.getDeployedCount() + " Processes Deployed Successfully");
    }

    protected abstract String[] getBpmnFiles(); 
    .
    .
    .
}
Run Code Online (Sandbox Code Playgroud)

5.简单的测试过程模型

首先,我们需要一个bpmn图,您可以找到它(SampleProcess.bpmn)。该过程有一个开始事件,一个用户任务和一个结束事件。

bpmn xml内容是:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1" targetNamespace="http://org.eclipse.bpmn2/default/process">
  <bpmn2:process id="process_1" name="sampleProcess">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>SequenceFlow_2</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:endEvent id="EndEvent_1">
      <bpmn2:incoming>SequenceFlow_3</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_2" sourceRef="StartEvent_1" targetRef="UserTask_1"/>
    <bpmn2:userTask id="UserTask_1" name="User Task 1">
      <bpmn2:incoming>SequenceFlow_2</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_3</bpmn2:outgoing>
    </bpmn2:userTask>
    <bpmn2:sequenceFlow id="SequenceFlow_3" sourceRef="UserTask_1" targetRef="EndEvent_1"/>
  </bpmn2:process>
</bpmn2:definitions>
Run Code Online (Sandbox Code Playgroud)

6.运行测试

毕竟,您可以运行这样的测试:

public class SampleProcessTest extends BaseTest {

    @Override
    protected String[] getBpmnFiles() {
        return new String[] {"com/test/activiti/sampleProcess/SampleProcess.bpmn"};
    }
    @Test
    public void sampleFlowTest()
    {
        ProcessInstance pi = super.runtimeService.startProcessInstanceByKey("process_1");
        Task ut1 = super.taskService.createTaskQuery()
                                        .processInstanceId(pi.getId())
                                        .active()
                                        .singleResult();
        assertNotNull(ut1);
        super.taskService.complete(ut1.getId());
        HistoricProcessInstance historicProcess = super.historyService.createHistoricProcessInstanceQuery()
                                                                        .processInstanceId(pi.getId())
                                                                        .finished()
                                                                        .singleResult();

        assertNotNull("Process must be finished",historicProcess);

    }

}
Run Code Online (Sandbox Code Playgroud)

7.委托表达式示例

在源链接上有很多DelegateExpression的示例,但是现在我们创建一个示例BPMN流程,该流程具有两个服务任务,这些任务由DelegateExpression定义为使用Spring bean的Autowire:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="awProcess" name="My process" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <serviceTask id="servicetask1" name="Service Task" activiti:delegateExpression="${awServiceTask1}"></serviceTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
    <serviceTask id="servicetask2" name="Service Task" activiti:delegateExpression="${com.test.activiti.autowiredservicetask.AWServiceTask2}"></serviceTask>
    <sequenceFlow id="flow2" sourceRef="servicetask1" targetRef="servicetask2"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow3" sourceRef="servicetask2" targetRef="endevent1"></sequenceFlow>
  </process>      
</definitions>
Run Code Online (Sandbox Code Playgroud)

和AWServiceTask1:@Component(“ awServiceTask1”)公共类AWServiceTask1实现JavaDelegate {

    Logger logger = Logger.getLogger(AWServiceTask1.class);
    @Override
    public void execute(DelegateExecution execution) throws Exception {
        logger.info("Object Identity : " + this.toString());
    }

    @PostConstruct
    public void init()
    {
        logger.info("awServiceTask1 is created");
    }

}
Run Code Online (Sandbox Code Playgroud)

同样的方法是AWServiceTask2的代码,您可以在activiti-test上找到完整的源代码。测试类是:

public class TestAWServiceTask extends BaseTest {

    Logger logger = Logger.getLogger(TestAWServiceTask.class);
    public static String KEY = "awProcess";

    @Test
    public void autoWireTest()
    {
        processDeployer.printAllProcessDefinition();
        processEngine.getProcessEngine().getRuntimeService().startProcessInstanceByKey(KEY);
    }
    @Override
    protected String[] getBpmnFiles() {
        return new String[] {
                "com/test/activiti/autowiredservicetask/AutoWireServiceTask.bpmn"};
    }

}
Run Code Online (Sandbox Code Playgroud)

希望您能得到想要的答案