Skip to content

Testing with Java

Java tests use the Embedded engine’s server form: one tinyconductor --mode embedded process, driven over the REST API with the JDK’s HttpClient. Nothing is linked into the JVM.

The runnable project is testing/java in the examples download: Gradle, JUnit 5 and Jackson, Java 21.

From the container image:

Terminal window
export TINYCONDUCTOR_TOKEN=test-token
docker run --rm -d --name tinyconductor-test -p 127.0.0.1:8080:8080 \
-e CONDUCTOR_AUTH_CREDENTIALS_JSON='[{"token":"test-token","subject":"tests","tenantId":"default","kind":"service","actions":["*"]}]' \
registry.tinyfactory.ai/tinyblox/tinyconductor:0.1.0 --mode embedded

Or from the release archive for your platform (downloads are listed in Embedded mode); on loopback it needs no credential:

Terminal window
./tinyconductor-0.1.0-linux-x86_64/tinyconductor --mode embedded

The tests read TINYCONDUCTOR_URL (default http://127.0.0.1:8080) and, if the engine was started with credentials, TINYCONDUCTOR_TOKEN. In a pipeline, see CI recipes.

StepRequest
start cleanPOST /v1/embedded/reset
deployPOST /v1/deployments, multipart, one resource part per file
start an instancePOST /v1/process-instances {"processDefinitionId": "order-process", "variables": {…}}
take a jobPOST /v1/jobs/activation {"type": "charge-card", "timeout": 30000, "maxJobsToActivate": 1}
complete itPOST /v1/jobs/{jobKey}/completion {"leaseEpoch": …, "variables": {…}} (204)
move timePOST /v1/embedded/clock/advance-by {"milliseconds": 86400000}
find a user taskPOST /v1/user-tasks/search {"processInstanceKey": "…"}
complete itPOST /v1/user-tasks/{userTaskKey}/completion {"variables": {…}} (204)
assertGET /v1/embedded/records
@BeforeEach
void resetAndDeploy() throws Exception {
// Every test starts from an empty engine at the fixed epoch.
call("POST", "/v1/embedded/reset", null);
deploy("order.form", "application/json");
deploy("order-decisions.dmn", "application/xml");
deploy("order.bpmn", "application/xml");
}
@Test
void orderCompletesAfterTheReviewPeriod() throws Exception {
String key = call("POST", "/v1/process-instances", Map.of(
"processDefinitionId", "order-process",
"variables", Map.of("orderId", 4711, "amount", 99.9)))
.get("processInstanceKey").asText(); // keys are JSON strings
completeJob("charge-card", Map.of("charged", true));
// The 24-hour review timer fires inside this call; no sleeping or polling.
call("POST", "/v1/embedded/clock/advance-by", Map.of("milliseconds", 86_400_000L));
completeJob("send-invoice", Map.of());
JsonNode tasks = call("POST", "/v1/user-tasks/search", Map.of("processInstanceKey", key)).get("items");
assertEquals("confirm-shipment", tasks.get(0).get("elementId").asText());
call("POST", "/v1/user-tasks/" + tasks.get(0).get("userTaskKey").asText() + "/completion",
Map.of("variables", Map.of("shipped", true)));
Set<String> completed = new HashSet<>();
for (JsonNode record : call("GET", "/v1/embedded/records", null).get("records")) {
if (record.get("valueType").asText().equals("PROCESS_INSTANCE")
&& record.get("intent").asText().equals("ELEMENT_COMPLETED")
&& record.get("value").get("processInstanceKey").asText().equals(key)) {
completed.add(record.get("value").get("elementId").asText());
}
}
for (String element : new String[] {"order-process", "charge-card", "send-invoice", "confirm-shipment"}) {
assertTrue(completed.contains(element), element + " completed");
}
}

call, deploy and completeJob are small helpers over HttpClient in the example (src/test/java/example/OrderProcessTest.java); deploy builds the multipart body by hand, so no HTTP library is needed. Run it:

Terminal window
cd tinyconductor-0.1.0-examples/testing/java
gradle test

The Embedded server also serves the v2-shaped clock operations (PUT /v2/clock, POST /v2/clock/reset) and the v2 API, which is what the remote-runtime configuration of compatible Java process-testing libraries calls. Running such a suite unchanged against an Embedded engine is the intent, but it has not yet been verified end to end; until it is, write tests against the REST API as shown here. What compatibility covers is on the Compatibility page.