Testing Camunda BPMN scenario using test coverage extension

Published On: 2020/05/22

In the article Camunda BPMN testing with Mockito we have gone through the steps to do the testing of a BPMN using camunda-bpm-mockito library. In this article we look into the details of BPMN testing using community extension libraries camunda-bpm-assert-scenario and camunda-bpm-process-test-coverage

Maven Configuration

<dependency>
    <groupId>org.camunda.bpm.extension</groupId>
    <artifactId>camunda-bpm-assert-scenario</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.camunda.bpm.extension</groupId>
  <artifactId>camunda-bpm-process-test-coverage</artifactId>
  <version>0.3.2</version>
  <scope>test</scope>
</dependency>

BPMN Diagram

The business process we will be using to test is the budle ordering process.

This process calls the individual item order process and then delivers it to the given shipping address.

Create Test

As our process is a bundle ordering process, let us give the name of the test class as “BundleOrderingProcessTest”. Use the Deployment annotation of the camunda engine to give the paths of the BPMN and DMN files which are part of the ordering process.

@Deployment(resources = {
        "bpmn/bundle-ordering-process.bpmn",
        "bpmn/singleitem-ordering-process.bpmn",
        "dmn/identify-shipping-agent.dmn"
})
public class BundleOrderingProcessTest {

}

Now we need a process engine to run the deployed bpm process when the unit test runs. The library camunda-bpm-process-test-coverage provides TestCoverageProcessEngineRuleBuilder to build the ProcessEngineRule which could generate the test coverage.

    @Rule
    @ClassRule
    public static ProcessEngineRule rule =
            TestCoverageProcessEngineRuleBuilder.create()
                    .withDetailedCoverageLogging().build();
    @Mock private ProcessScenario bundleOrderApplication;
    @Mock private ProcessScenario singleOrderProcess;

The ProcessEngineRule initializes the process engine using the “camunda.cfg.xml” file given in the test resources root. If your project need to save complex objects in camunda, you may need Spin plugin for serialization and deserialization. If such case is there register the spin plugin in the bean defintion as provided in the configuration xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.camunda.bpm.extension.process_test_coverage.junit.rules.ProcessCoverageInMemProcessEngineConfiguration">

        <property name="history" value="audit" />
        <property name="databaseSchemaUpdate" value="true" />
        <property name="jobExecutorActivate" value="false" />
        <property name="expressionManager">
            <bean class="org.camunda.bpm.engine.test.mock.MockExpressionManager" />
        </property>
        <property name="idGenerator">
            <bean class="org.camunda.bpm.engine.impl.persistence.StrongUuidGenerator"/>
        </property>
        <property name="processEnginePlugins">
            <list>
                <bean id="spinPlugin"
                      class="org.camunda.spin.plugin.impl.SpinProcessEnginePlugin" />
            </list>
        </property>

    </bean>
</beans>

Bean Registration with Mockito

Create a method with @Before annotation to load the process variables and the mockito stubs common for all test scenarios.

If in case you have used the spring bean names in the deligate expression of the task configuration, register it with the mockito.

        MockitoAnnotations.initMocks(this);

        Mocks.register("bundleProcessStart", new BundleProcessStart());
        Mocks.register("processOrder",new ProcessOrder());
        Mocks.register("confirmDeliveryAgent",new ConfirmDeliveryAgent());

        variables = Variables.createVariables()
                .putValue("orderId", "X4399T00")
                .putValue("orderDeliveries", deliveries);

        when(bundleOrderApplication.runsCallActivity("CallActivitySingleOrderProcessing"))
                .thenReturn(Scenario.use(singleOrderProcess));

        when(singleOrderProcess.waitsAtUserTask("Task_Packing")).thenReturn((task) -> {
            task.complete(withVariables("packingType", "Bubble Bags"));
        });

Task Handling

We could override the mockito stubing provided in the setup method according to the test scenario. In the test method for glass item ordering scenario, the packing task needs to add the process variable packing type with value “Packing Peanuts” instead of the default value “Bubble Bags”.

In the verify stubing method, we could check whether the tasks which are to be executed is actually executed and completed.

    @Test
    public void testGlassItemOrderingScenario() {
        when(singleOrderProcess.waitsAtUserTask("Task_Packing")).thenReturn((task) -> {
            task.complete(withVariables("packingType", "Packing Peanuts"));
        });

        Scenario scenario = Scenario.run(bundleOrderApplication)
                .startByKey("bundle_ordering_process", variables)
                .execute();

        assertThat(scenario.instance(bundleOrderApplication)).calledProcessInstance("singleitem_ordering_process");

        verify(bundleOrderApplication,times(3)).hasCompleted("CallActivitySingleOrderProcessing");
        verify(bundleOrderApplication, times(3)).hasCompleted("Task_Delivery");
        verify(bundleOrderApplication).hasFinished("EndEventDeliveryCompleted");

        //verify(documentRequest, never()).hasCompleted("ReceiveTaskWaitForDocuments");

    }

Test Coverage

When we run the “mvn clean package”, the test will be executed and the coverage report will be generated into the target/process-test-coverage folder. The test execution generates html report per bpmn and scenario. In this article, as I have tested only one scenario covering two bpmn process, it generates two html files.

Conclusion

The source code of this project is available in the Github repository

comments powered by Disqus