Skip to main content
Version: 8.8 (unreleased)

Utilities

There are different utilities that can help you to write your process test.

Manipulate the clock

The Camunda runtime uses an internal clock to execute process instances and to calculate when a BPMN timer event is due. In a test, you can use CamundaProcessTestContext to manipulate the clock.

When to use it:

  • Trigger an active BPMN timer event
  • Test scenarios that require a specific date or time, for example, a leap year
@Test
void shouldTriggerTimerEvent() {
// given: a process instance waiting at a BPMN timer event

// when
assertThat(processInstance).hasActiveElements("wait_2_days");

processTestContext.increaseTime(Duration.ofDays(2));

// then
assertThat(processInstance).hasCompletedElements("wait_2_days");
}

Mock job workers

You can mock a job worker to simulate its behavior without invoking the actual worker. The mock handles all jobs of the given job type.

When to use it:

  • Test the process in isolation from the actual job workers
  • Simulate different outcomes of a job worker (success, BPMN error)
  • Mock disabled job workers or Connectors

Complete job

The mock completes jobs with/without variables.

@Test
void shouldCompleteJob() {
// given: mock job worker for the job type "send-email"
// 1) Complete jobs without variables
rocessTestContext.mockJobWorker("send-email").thenComplete();

// 2) Complete jobs with variables
final Map<String, Object> variables = Map.of(
"emailSent", true,
"timestamp", "2024-01-01T10:00:00Z"
);
processTestContext.mockJobWorker("send-email").thenComplete(variables);

// when: create a process instance
// then: verify that the process instance completed all tasks
}

Throw BPMN error

The mock throws BPMN errors for jobs with the given error code and with/without variables.

@Test
void shouldThrowBpmnError() {
// given: mock job worker for the job type "validate-order"
// 1) Throw BPMN errors with error code "INVALID_ORDER"
processTestContext.mockJobWorker("validate-order").thenThrowBpmnError("INVALID_ORDER");

// 2) Throw BPMN errors with error code "INVALID_ORDER" and variables
final Map<String, Object> variables = Map.of(
"reason", "The order exceeds the item limit."
);
processTestContext
.mockJobWorker("validate-order")
.thenThrowBpmnError("INVALID_ORDER", variables);

// when: create a process instance
// then: verify that the process instance handled the BPMN error
}

Custom handler

You can implement a custom handler to mock more complex behaviors.

@Test
void shouldUseCustomHandler() {
// given: mock job worker for the job type "calculate-discount"
processTestContext
.mockJobWorker("calculate-discount")
.withHandler(
(jobClient, job) -> {
final Map<String, Object> variables = job.getVariablesAsMap();
final double orderAmount = (double) variables.get("orderAmount");
final double discount = orderAmount > 100 ? 0.1 : 0.0;

jobClient.newCompleteCommand(job).variable("discount", discount).send().join();
});

// when: create a process instance
// then: verify that the process instance has the expected variables
}

Mock child processes

You can mock a child process for a call activity to simulate its output without executing the actual child process. The mock deploys a dummy process with the given process ID that returns the given variables.

When to use it:

  • Test the parent process in isolation from the actual child process
  • Simulate different outcomes of a child process
  • Mock a non-existing child process
@Test
void shouldMockChildProcess() {
// given: mock child process with the process ID "payment-process"
// 1) Complete the child process without variables
processTestContext.mockChildProcess("payment-process");

// 2) Complete the child process with variables
final Map<String, Object> variables = Map.of(
"paymentStatus", "completed",
"transactionId", "TXN-12345"
);
processTestContext.mockChildProcess("payment-process", variables);

// when: create a process instance
// then: verify that the process instance completed the call activity
}

Mock DMN decisions

You can mock a DMN decision for a business rule task to simulate its output without evaluating the actual DMN decision. The mock deploys a dummy DMN decision with the given decision ID that returns the given variables.

When to use it:

  • Test the process with the business rule task in isolation from the actual DMN decision
  • Simulate different outcomes of a DMN decision
  • Mock a non-existing DMN decision
@Test
void shouldMockDmnDecision() {
// given: mock DMN decision with the decision ID "credit-check-decision"
final Map<String, Object> variables = Map.of(
"approved", true,
"riskLevel", "low",
"creditLimit", 5000
);
processTestContext.mockDmnDecision("credit-check-decision", variables);

// when: create a process instance
// then: verify that the process instance completed the business rule task
}