Closed bennobuilder closed 1 week ago
hi @bennobuilder,
on branch issue/192 (see commit) I added an example process with a multi instance call activity that uses a collection expression ${elements}
and element variable element
. A test starts a test case with variable elements=["a", "b", "c"] and verifies the loop count as well as the variables at the call activity within the multi instance.
it is a bit tricky to test the local element variable, used within the multi instance.
in the verify
method of the call activity handler of the multi instance a ProcessInstanceAssert
(here named piAssert
) is provided. but it can only be used to assert variables that are on process instance level, e.g. elements
. to verify local variables, like the element variable, the local variables of the related exectution must be retrieved. to do this, the execution ID is required. therefore the historic activity instance of the multi instance body must be found.
tc.handleCallActivity().handle(0).verify((piAssert, callActivityDefinition) -> {
piAssert.variables().containsKey("elements"); // assertion of process scoped variables only (e.g. collection)
// find process instance of test case, e.g. by business key
var pi = tc.getProcessEngine().getRuntimeService().createProcessInstanceQuery()
.processInstanceBusinessKey("bk")
.singleResult();
// find historic activity instance of call activity in multi instance scope
var historicActivityInstance = tc.getProcessEngine().getHistoryService().createHistoricActivityInstanceQuery()
.activityId("multiInstanceCallActivity#multiInstanceBody") // BPMN element ID + #multiInstanceBody
.singleResult();
// get local variables (including element variable of collection) of related execution
var localVariables = tc.getProcessEngine().getRuntimeService().getVariablesLocal(historicActivityInstance.getExecutionId());
assertThat(localVariables.get("element"), equalTo("a"));
});
when the element variable is propagated to the subprocess via delegate variable mapping, in mapping propagation or in mappings, the variable value is much easier to assert.
tc.handleCallActivity().handle(0).verifyInput(variables -> {
assertThat(variables.getVariable("element"), equalTo("a"));
});
tc.handleCallActivity().handle(1).verifyInput(variables -> {
assertThat(variables.getVariable("element"), equalTo("b"));
});
tc.handleCallActivity().handle(2).verifyInput(variables -> {
assertThat(variables.getVariable("element"), equalTo("c"));
});
this example shows that a multi instance call activity with collection expression is supported.
regarding your test, I'm not sure what DelegateMock
is doing. maybe the emails variable is not set correctly.
i hope the example helps. if you have more questions, feel free to ask.
best regards!
Hi @gclaussn,
Thanks for the detailed explanation and example. After further investigation, I identified two issues that contributed to my failing tests.
I found that defining Outputs
in a Delegate expression can override initially set variables (e.g., by tc1.createExecutor().withVariable(..)
). This caused the issue I initially encountered, where I expected variables to persist but found they were overwritten by an Output (without values) defined in the modeler (see Screenshot 1
).
The bpmn-driven-testing
library behaves differently when integrated with Spring Boot compared to a plain Java setup.
Running multiple test cases simultaneously results in exceptions like OptimisticLockingException
and ProcessEngineException
(see Screenshot 2
):
org.camunda.bpm.engine.ProcessEngineException: ENGINE-14026 No job found with id 'a35e4042-66c8-11ef-a37f-00059a3c7a00'
org.camunda.bpm.engine.OptimisticLockingException: ENGINE-03005 Execution of 'DELETE MessageEntity[b9969346-66c8-11ef-9cb8-00059a3c7a00]' failed. Entity was updated by another transaction concurrently.
Running only the first test case (similar to my initial test case but simplified, see Test Case
) results in an AssertionError
(see Screenshot 3
):
java.lang.AssertionError: Expected at least one job for activity 'Call_Participant_2'
When I remove Spring Boot (i.e., the SpringBootTest
annotation), the tests run as expected without exceptions (see Screenshot 4
). I confirmed this by setting the expected loop count to 2 and anticipating an error.
These issues were observed using the following files, added to the advanced-spring-boot
integration tests (checked out locally on Windows 11 with Java 21):
Is there a known issue with the bpmn-driven-testing
library in a Spring Boot environment? Do you recommend using Spring Boot for these tests, or would sticking with plain Java be preferable? We chose Spring Boot because our project uses it but for the tests we would also be fine using plain Java, I guess.
Thanks :) and best regards
hi @bennobuilder,
I think I know what the problem with your Spring Boot tests might be.
the advanced-spring-boot integration test does not look like a project that I have usually under test - since it tests only the configration of the process engine, provided by the camunda-bpm-spring-boot-starter
, when exposing the BpmndtProcessEnginePlugin
as a Spring bean.
when running process tests (with or without bpmn-driven-testing), the application.yaml
under src/test/resources must disable the job executor via:
camunda:
bpm:
job-execution:
enabled: false
by default the job executor is enabled and runs in parallel in a separate thread. this makes the process tests not deterministic and leads to the exceptions you described (No job found
or Entity was updated by another transaction concurrently
). therefore it must be disabled while testing. I will add this configuration to the Spring Boot integration test to make it complete.
please give me a quick feedback if this makes your Spring Boot based tests run successfully.
best regards
Hi @gclaussn,
Thanks for your suggestion. I tested it in a demo project, and it works perfectly. However, for our main project, we decided to proceed without Spring Boot testing for now since it's easier to setup and doesn't seem to be necessary to test the BPMN, even though the project itself uses Spring Boot. Your library has made the overall testing process much smoother.
Thanks again, and cheers :)
I’m currently working on a test case using BPMN-Driven-Testing and encountered an issue while trying to test a multi-instance subprocess configured with a collection (
camunda:collection
, see image).In my test, I expect the
verifyLoopCount
to reflect the size of the collection (in this case,2
for a list of two emails), but it always returns0
. The variables are being consumed (-> to verify ProcessInstance contains variableemails
but empty).Is there support for testing
camunda:collection
in this context (couldn't find any test) or is only loop cardinality supported. An example or guidance would be appreciated.Thanks :)