A common way to call a reusable subprocess is to use a call activity in the BPMN 2.0 model. By using a call activity it is only necessary to add the process key of the subprocess to call and the version of it to the call activity properties. Thus, the modeling can be continued. Apart from this it is possible to define process variables to pass between the main and the subprocess.

But during unit testing the main process and all subprocesses referenced by the defined process keys must exist in the process engine repository.

The easiest way to solve this problem is to replace the defined process by the process key of a mock process which must exist in repository. But it is not advisable to change a process model for testing purposes only. It takes time to undo these changes when the real subprocess is completed. Moreover such changes could be forgotten, cause it is already tested successfully.

Creating a mock process with the same process key of the real subprocess is not convenient if there exist more than a few subprocesses which is often the reality.

A handy alternative since version 7.1 of camunda BPM is the use of the BPMN Model API.
It makes it possible to create, edit and parse BPMN 2.0 models as pure Java code.

Let’s make an example

The following process model consists of a main process with two call activities.

Main Proces with two Call-Activities
Main Proces with two Call-Activities

To have a reusable solution, a helper method is created and used by the test.
It creates a model instance by using BPMN Model API and deploys it in the given process engine repository as shown below.

[code wraplines=“false“ language=“java“ collapse=“true“]

/**
* Create and deploy a process model with one logger delegate as service task.
*
* @param origProcessKey
* key to call
* @param mockProcessName
* process name
* @param fileName
* file name without extension
*/
private void mockSubprocess(String origProcessKey, String mockProcessName,
String fileName) {
BpmnModelInstance modelInstance = Bpmn
.createExecutableProcess(origProcessKey).name(mockProcessName)
.startEvent().name(„Start Point“).serviceTask()
.name(„Log Something for Test“)
.camundaClass(MockLoggerDelegate.class.getName()).endEvent()
.name(„End Point“).done();
repositoryService().createDeployment()
.addModelInstance(fileName + „.bpmn“, modelInstance).deploy();
}

[/code]

The primary goal of this test is to ensure that the main process is ended successfully. Therefore a model instance for each call activity is created and deployed in the given repository. The main process is deployed via @Deployment annotation. Following code snippet illustrates the implementation.

[code wraplines=“false“ language=“java“ collapse=“true“]

@Test
@Deployment(resources = „mainProcess.bpmn“)
public void shouldEnd() {

// mock first sub process
this.mockSubprocess(„firstSubProcessKey“, „Mocked First Sub Process“,
„mockedFirstSubProcess“);

// mock second sub process
this.mockSubprocess(„secondSubProcessKey“, „Mocked Second Sub Process“,
„mockedSecondSubProcess“);

// start main process
ProcessInstance mainInstance = runtimeService().startProcessInstanceByKey(
„mainProcessKey“);

assertThat(mainInstance).isEnded();
}

[/code]

The created model instances look equally – it consists of a start event, a service task which references a delegate and an end event. Following code snippet shows the simple implementation of the used delegate.

[code wraplines=“false“ language=“java“ collapse=“true“]

public class MockLoggerDelegate implements JavaDelegate {

private final Logger LOGGER = Logger.getLogger(MockLoggerDelegate.class
.getName());

@Override
public void execute(DelegateExecution execution) throws Exception {
LOGGER.info(„\n\n …“ + MockLoggerDelegate.class.getName()
+ “ invoked by “ + „processDefinitionId=“
+ execution.getProcessDefinitionId() + „, activtyId=“
+ execution.getCurrentActivityId() + „, activtyName='“
+ execution.getCurrentActivityName() + „‚“ + „, processInstanceId=“
+ execution.getProcessInstanceId() + „, businessKey=“
+ execution.getProcessBusinessKey() + „, executionId=“
+ execution.getId() + “ \n\n“);
}

}

[/code]

Of course, it’s possible to individualize these mocks dependant on your test case. For example, you could create a delegate for each sub process which set specific process variables. This example demonstrates only the capability of this solution.

Keep in mind, it is not recommended to replace your process models by using the BPMN Model API. But it is very useful to solve small problems in a simple way – just a few lines of Java code. After completion a subprocess it is advisable to test the interaction with the main process, too.

And of course, do not forget to write automated integration tests 😉

Alle Beiträge von Halil Hancioglu

2 Kommentare

Antwort an Jakob Freund Antwort verwerfen