Unit testing strategy using transient variables in Spring boot

Hello All,

I have the below flow which has a service task " Populate list Items" . This has a java delegate which create a transient json object variable and populates the data. Below is the code for it .In the call activity i iterate over the “items” collection to create new bpmn instance.

image

In the java delegate i have the below code

@Component("GetItemData")
 public class GetItemData implements JavaDelegate {

 @Override
public void execute(DelegateExecution execution) throws Exception {
    String itemsList = "{\n" +
            "  \"firstName\": \"John\",\n" +
            "  \"lastName\" : \"doe\",\n" +
            "  \"age\"      : 26,\n" +
            "  \"items\": [\n" +
            "    {\n" +
            "      \"value\"  : \"iPhone\",\n" +
            "      \"category\": \"mobile\"\n" +
            "    },\n" +
            "    {\n" +
            "      \"value\"  : \"Pixel\",\n" +
            "      \"number\": \"mobile\"\n" +
            "    }\n" +
            "  ]\n" +
            "}";
    Spin itemDataJSON = JSON(itemsList);
    TypedValue typedTransientObjectValue = Variables.objectValue(itemDataJSON, true).serializationDataFormat(Variables.SerializationDataFormats.JSON).create();
    execution.setVariable("itemsData", typedTransientObjectValue);
    }

}

Unit Test : - Ideally i would want to have to have a separate test case for the Java delegate and the test case for the “Process” . I have mocked the java delegate but the test case is failing at the “call activity” with message “Unknown property used in expression: ${itemsData.prop(“items”).elements()}. Cause: Cannot resolve identifier ‘itemsData’” since the Java delegate is mocked and its a void method for which i cannot put a Mockito.when().thenReturn()

@RunWith(MockitoJUnitRunner.class)
public class TestSampleFlow {

@Rule
public final ProcessEngineRule engine = new StandaloneInMemoryTestConfiguration().rule();

@Mock
private GetItemData getItemData;

@Before
public void setup() {
    // register a bean name with mock expression manager
    MockitoAnnotations.initMocks(this);
   Mocks.register("GetItemData", getItemData);
}

@Test
@Deployment(resources = {"SampleFlow.bpmn", "process1"})
public void createSampleProcess() throws Exception {
    RuntimeService runtimeService = engine.getRuntimeService();
    Mockito.doNothing().when(getItemData).execute(any());
    HistoryService historyService = engine.getHistoryService();
    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("SampleFlow", "ORDER-01");
    List<HistoricProcessInstance> processInstancesList = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey("ORDER-01").list();
    assertEquals(processInstancesList.size(), 3);

}

}

Please let me know if i am in the right path for unti Testing and if there are any work around to get this working .

Thanks
Dinesh

Your problem: you registered a mockito bean for your delegate. But when that mock gets called, it simpy does nothing. So it does not modify the process instance and your follow up task fails because expected variables are not set.

You have to configure behavior by telling mockito to do st. when the delegate is called:

doAnswer(i -> { i.<DelegateExecution>getArgument(0).setVariable("xxx", "yyy"); return null; } ).when(getItemData).execute(any(DelegateExecution.class));

As this is common behavior when working with mockito and camunda, I wrote the camunda-bpm-mockito extension, check it out, it will make your life easier: https://github.com/camunda/camunda-bpm-mockito

@jangalinski - Thanks for the detailed explanation. Just looked at Camunda-bpm-mockito library and it has lot of helper classes which will be making work easier .Before i use it just wanted to check if it has any Camunda version dependency ? We are on Camudna springboot 7.13.
Also i was able to successfully mock the java delegate with the solution provided by you but now it throws a different error mentioned in this post Error - Cannot find serialize for value 'ObjectValue from jUnit . Since you provided the correct answer for this topic i will mark it as a “solution” . Thanks once again .

I just checked the POM for Camunda BPM mockito . It has the latest Camunda version 7.13 .

Thanks
Dinesh

1 Like

the extension follows a simple versioning model: the “middle number” (in case of 4.13.0 -> 13) is the camunda “middle number” its build against, so 4.13.0 matches 7.13.0.

Unfortunately this is required from time to time due to backward incompatible API changes of camunda when it comes to new methods on the delegate interfaces …

1 Like

Thanks for the clarification !!