Skip to content

Commit

Permalink
feat: added additional verifier for external tasks and their local va…
Browse files Browse the repository at this point in the history
…riables
  • Loading branch information
gclaussn committed Oct 28, 2023
1 parent 4488290 commit 87caa1c
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.camunda.bpm.engine.externaltask.LockedExternalTask;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.test.assertions.ProcessEngineTests;
import org.camunda.bpm.engine.test.assertions.bpmn.ExternalTaskAssert;
import org.camunda.bpm.engine.test.assertions.bpmn.ProcessInstanceAssert;
import org.camunda.bpm.engine.variable.VariableMap;
import org.camunda.bpm.engine.variable.Variables;
Expand All @@ -36,6 +37,7 @@ public class ExternalTaskHandler {
private String errorMessage;

private BiConsumer<ProcessInstanceAssert, String> verifier;
private BiConsumer<ExternalTaskAssert, Map<String, Object>> taskVerifier;

private Consumer<String> action;
private Consumer<ExternalTask> taskAction;
Expand All @@ -55,6 +57,13 @@ protected void apply(ProcessInstance pi) {
if (verifier != null) {
verifier.accept(ProcessEngineTests.assertThat(pi), topicName);
}
if (taskVerifier != null) {
ExternalTask task = query(pi);

Map<String, Object> localVariables = processEngine.getRuntimeService().getVariablesLocal(task.getExecutionId());

taskVerifier.accept(ProcessEngineTests.assertThat(task), localVariables);
}

if (action != null) {
action.accept(topicName);
Expand Down Expand Up @@ -169,7 +178,7 @@ public boolean isWaitingForBoundaryEvent() {
return action == null && taskAction == null;
}

private ExternalTask queryAndLock(ProcessInstance pi) {
private ExternalTask query(ProcessInstance pi) {
ExternalTaskService externalTaskService = processEngine.getExternalTaskService();

ExternalTask externalTask = externalTaskService.createExternalTaskQuery()
Expand All @@ -183,6 +192,14 @@ private ExternalTask queryAndLock(ProcessInstance pi) {
throw new AssertionError(msg);
}

return externalTask;
}

private ExternalTask queryAndLock(ProcessInstance pi) {
ExternalTask externalTask = query(pi);

ExternalTaskService externalTaskService = processEngine.getExternalTaskService();

try {
externalTaskService.lock(externalTask.getId(), WORKER_ID, TimeUnit.SECONDS.toMillis(60L));
} catch (BadUserRequestException e) {
Expand All @@ -209,6 +226,19 @@ public ExternalTaskHandler verify(BiConsumer<ProcessInstanceAssert, String> veri
return this;
}

/**
* Verifies the external task's waiting state.
*
* @param taskVerifier Verifier that accepts an {@link ExternalTaskAssert} instance and the task's
* local variables.
*
* @return The handler.
*/
public ExternalTaskHandler verifyTask(BiConsumer<ExternalTaskAssert, Map<String, Object>> taskVerifier) {
this.taskVerifier = taskVerifier;
return this;
}

/**
* Applies no action at the external task's wait state. This is required to wait for events (e.g.
* message, signal or timer events) that are attached as boundary events on the activity itself or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.camunda.community.bpmndt.api;

import static com.google.common.truth.Truth.assertThat;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;

import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.test.assertions.ProcessEngineTests;
import org.camunda.bpm.engine.test.assertions.bpmn.ProcessInstanceAssert;
import org.camunda.community.bpmndt.test.TestPaths;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class ExternalTaskInputOutputTest {

@RegisterExtension
public TestCase tc = new TestCase();

private ExternalTaskHandler handler;

@BeforeEach
public void setUp() {
handler = new ExternalTaskHandler(tc.getProcessEngine(), "externalTask", "test-topic");
}

@Test
public void testVerifyTask() {
handler.verify((pi, topicName) -> {
pi.variables().containsEntry("i", 10L);

assertThat(topicName).isEqualTo("test-topic");
});

handler.verifyTask((externalTaskAssert, localVariables) -> {
externalTaskAssert.hasTopicName("test-topic");

assertThat(localVariables).containsEntry("increment", 11L);
});

tc.createExecutor()
.withVariable("i", 10L)
.verify(pi -> {
pi.isEnded();

pi.variables().containsEntry("decrement", 10L);
})
.execute();
}

private class TestCase extends AbstractJUnit5TestCase<TestCase> {

@Override
protected void execute(ProcessInstance pi) {
assertThat(pi).isNotNull();

ProcessInstanceAssert piAssert = ProcessEngineTests.assertThat(pi);

piAssert.hasPassed("startEvent").isWaitingAt("externalTask");

instance.apply(handler);

piAssert.hasPassed("externalTask", "endEvent").isEnded();
}

@Override
protected InputStream getBpmnResource() {
try {
return Files.newInputStream(TestPaths.advanced("externalTaskInputOutput.bpmn"));
} catch (IOException e) {
return null;
}
}

@Override
public String getProcessDefinitionKey() {
return "externalTaskInputOutput";
}

@Override
public String getStart() {
return "startEvent";
}

@Override
public String getEnd() {
return "endEvent";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="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:bpmndt="http://camunda.org/schema/extension/bpmn-driven-testing" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_024dl6t" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.4.0">
<bpmn:process id="externalTaskInputOutput" isExecutable="true">
<bpmn:extensionElements>
<bpmndt:testCases>
<bpmndt:testCase>
<bpmndt:path>
<bpmndt:node>startEvent</bpmndt:node>
<bpmndt:node>externalTask</bpmndt:node>
<bpmndt:node>endEvent</bpmndt:node>
</bpmndt:path>
</bpmndt:testCase>
</bpmndt:testCases>
</bpmn:extensionElements>
<bpmn:startEvent id="startEvent">
<bpmn:outgoing>Flow_0z1bh05</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_0z1bh05" sourceRef="startEvent" targetRef="externalTask" />
<bpmn:serviceTask id="externalTask" camunda:type="external" camunda:topic="test-topic">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:inputParameter name="increment">${i + 1}</camunda:inputParameter>
<camunda:outputParameter name="decrement">${increment - 1}</camunda:outputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0z1bh05</bpmn:incoming>
<bpmn:outgoing>Flow_08kf56i</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="endEvent">
<bpmn:incoming>Flow_08kf56i</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_08kf56i" sourceRef="externalTask" targetRef="endEvent" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="externalTaskInputOutput">
<bpmndi:BPMNEdge id="Flow_0z1bh05_di" bpmnElement="Flow_0z1bh05">
<di:waypoint x="215" y="117" />
<di:waypoint x="270" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_08kf56i_di" bpmnElement="Flow_08kf56i">
<di:waypoint x="370" y="117" />
<di:waypoint x="432" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="startEvent">
<dc:Bounds x="179" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_009m7q1_di" bpmnElement="externalTask">
<dc:Bounds x="270" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1jq562r_di" bpmnElement="endEvent">
<dc:Bounds x="432" y="99" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.example.it;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.Rule;
import org.junit.Test;

import generated.externaltaskinputoutput.TC_startEvent__endEvent;

public class ExternalTaskInputOutputTest {

@Rule
public TC_startEvent__endEvent tc = new TC_startEvent__endEvent();

@Test
public void testExecute() {
tc.handleExternalTask().verifyTask((externalTaskAssert, localVariables) -> {
externalTaskAssert.hasTopicName("test-topic");

assertThat(localVariables.get("increment"), is(11L));
});

tc.createExecutor()
.withVariable("i", 10L)
.verify(pi -> {
pi.isEnded();

// verify output variables
pi.variables().containsEntry("decrement", 10L);
})
.execute();
}
}

0 comments on commit 87caa1c

Please sign in to comment.