Search code examples
testingbpmncamunda

Dynamic testing for any camunda bpmn process


I am working on a Camunda java code and i am looking for a testing methodology that i can use to test any of my bpmn processes.

i have made some google search and i found on Camunda documentation some ideas about unit testing but it is do test for a specific bpmn model . i need one to test any bpmn model (just by passing name of bpmn file and id of process etc) the strategy should take into account the integration with DB to get candidate (user&group) for any expected path.i know maybe i can't do that but i have a large model and it will be time waste to test all of it in traditional ways.


Solution

  • Mohammad, your question is interesting - this goal can be achieved (test on bpmn can be dynamic), if we talk about not very detailed test. Look at my code below, written by your idea of such common test (as i understood it, of course) I use camunda-bpm-assert-scenario and camunda-bpm-assert libs in it.

    First of all you gives to your test info about "wait states" in testing process (this can be done by json file - for not to change the code)

        // optional - for mocking services for http-connector call, et.c.
        private Map<String, Object> configs = withVariables(
                "URL_TO_SERVICE", "http://mock-url.com/service"
        );
    
        private Map<String, Map<String, Object>> userTaskIdToResultVars = new LinkedHashMap<String, Map<String, Object>>() {{
            put("user_task_0", withVariables(
                    "a", 0
            ));
            put("user_task_1", withVariables(
                    "var0", "var0Value",
                    "var1", "var1Value"));
        }};
    
        // optional - if you want to check vars during process execution
        private Map<String, Map<String, Object>> userTaskIdToAssertVars = new LinkedHashMap<String, Map<String, Object>>() {{
            put("user_task_1", withVariables(
                    "a", 0
            ));
        }};
    

    Then you mocking user tasks (and other wait states) with given info:

    @Mock
        private ProcessScenario processScenario;
    
        @Before
        public void defineHappyScenario() {
            MockitoAnnotations.initMocks(this);
    
            for (String taskId : userTaskIdToResultVars.keySet()) {
                when(processScenario.waitsAtUserTask(taskId)).thenReturn(
                        (task) -> {
                            // optional - if you want to check vars during process execution
                            Map<String, Object> varsToCheck = userTaskIdToAssertVars.get(taskId);
                            if (varsToCheck != null) {
                                assertThat(task.getProcessInstance())
                                        .variables().containsAllEntriesOf(varsToCheck);
                            }
    
                            task.complete(userTaskIdToResultVars.get(taskId));
                        });
            }
    
            // If it needs, we describe mocks for other wait states in same way, 
            // when(processScenario.waitsAtSignalIntermediateCatchEvent(signalCatchId).thenReturn(...);
    
        }
    

    And your test will be anything like this:

    @Test
        @Deployment(resources = "diagram_2.bpmn")
        public void testHappyPath() {
            Scenario scenario = Scenario.run(processScenario).startByKey(PROCESS_DEFINITION_KEY, configs).execute();
            ProcessInstance process = scenario.instance(processScenario);
            assertThat(process).isStarted();
    
            assertThat(process).hasPassedInOrder(     //  or check execution order of all elements -- not only wait-states (give them in additional file)
                    userTaskIdToResultVars.keySet().toArray(new String[0])     //   user_task_0, user_task_1
            );
            assertThat(process).isEnded();
        }
    

    Hope this helps in your work.