cancel
Showing results for 
Search instead for 
Did you mean: 

Unit Test cases for Custom Java Service Task

babjikundateeri
Champ in-the-making
Champ in-the-making
Hi,

I am new to activiti.

I am not able to figure out the way to write test cases for custom java delegate classes.
below is my test code snippet,
```
public class WorkFlowTest {

    @Rule
    public ActivitiRule activitiRule = new ActivitiRule();

    @Test
    @Deployment(resources = {"testemailflow.bpmn20.xml"})
    public void activitiTest() {
        Map<String, Object>  variables = new HashMap<>();
        RuntimeService runtimeService = activitiRule.getRuntimeService();
        runtimeService.startProcessInstanceByKey("testemailflow", variables);
        System.out.println(runtimeService);
    }
}
```
and my service task is as below
```
<serviceTask id="sid-3E402CB5-51C0-4BB9-9483-941C0BBB7128" name="contact picker" activiti:delegateExpression="${contactPickerTaskDelegation}">
            <extensionElements>
                <activiti:field name="contactPickerRuleId">
                    <activiti:string><![CDATA[7]]></activiti:string>
                </activiti:field>
            </extensionElements>
        </serviceTask>
```
my delegate code is as below
```
public class ContactPickerTaskDelegation implements JavaDelegate {
   private Expression contactPickerRuleId;

  @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
         LOGGER.debug("contactPickerRuleId " + contactPickerRuleId.getValue(delegateExecution).toString());
         List<Contact> contacts;  // doing something to get contacts
         delegateExecution.setVariable("contacts", contacts);
   }
}
``
while running the test case i' end-up with the exception like below
```
org.activiti.engine.ActivitiException: Unknown property used in expression: ${contactPickerTaskDelegation}

   at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:53)
   at org.activiti.engine.impl.bpmn.helper.DelegateExpressionUtil.resolveDelegateExpression(DelegateExpressionUtil.java:37)
   at org.activiti.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior.execute(ServiceTaskDelegateExpressionActivityBehavior.java:85)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:60)
```


My Application is using `spring-boot`.

Thanks in advance.
8 REPLIES 8

warper
Star Contributor
Star Contributor
Hi babjikundateeri,
Please provide relevant part of process definition. Looking at exception, I think you use delegate expression type of service task, and they need process instance variable or accessible spring bean with name/id "contactPickerTaskDelegation" to start with.
Probably you can use java class type of service task and specify your class path directly.

Also, please take a look at previous discussion of similar case:
https://forums.activiti.org/content/how-create-variable-javaservicetask

babjikundateeri
Champ in-the-making
Champ in-the-making
Hi warper,

Here is my process definition,

<code>
  <process id="TestMultiInstance" name="TestMultiInstance" isExecutable="true">
    <startEvent id="startEvent1"/>
    <sequenceFlow id="sid-6186FC5D-9FC7-4A36-948B-36C914A69AB8" sourceRef="startEvent1" targetRef="sid-39AAD947-3626-4B45-8DCF-4D07636B76B1"/>
    <serviceTask id="sid-39AAD947-3626-4B45-8DCF-4D07636B76B1" name="Contact Picker" activiti:delegateExpression="${contactPickerTaskDelegation}">
      <extensionElements>
        <activiti:field name="contactPickerRuleId">
          <activiti:string><![CDATA[7]]></activiti:string>
        </activiti:field>
      </extensionElements>
    </serviceTask>
    <subProcess id="sid-DEA02220-00E9-44E6-B5D2-0A81B5E891F3" name="subProcess" activiti:async="true" activiti:exclusive="false">
      <multiInstanceLoopCharacteristics isSequential="true" activiti:collection="contacts" activiti:elementVariable="contact"/>
      <startEvent id="sid-BE04B538-3E57-4208-87A4-DC66E69674F8"/>
      <serviceTask id="sid-BBD8C2E2-2EAD-4106-85A6-C95B9E649EF3" name="Email" activiti:delegateExpression="${fealtiEmailTaskDelegation}">
        <extensionElements>
          <activiti:field name="emailTemplateId">
            <activiti:string><![CDATA[30003]]></activiti:string>
          </activiti:field>
        </extensionElements>
      </serviceTask>
      <endEvent id="sid-C2CC2D3B-D9DB-486F-8D22-F9BFDB09F228"/>
      <sequenceFlow id="sid-81DF9E03-34D3-4482-82E5-926067174ED8" sourceRef="sid-BE04B538-3E57-4208-87A4-DC66E69674F8" targetRef="sid-BBD8C2E2-2EAD-4106-85A6-C95B9E649EF3"/>
      <sequenceFlow id="sid-52C2E732-AA74-4229-AB8B-95A54BF7A674" sourceRef="sid-BBD8C2E2-2EAD-4106-85A6-C95B9E649EF3" targetRef="sid-C2CC2D3B-D9DB-486F-8D22-F9BFDB09F228"/>
    </subProcess>
    <sequenceFlow id="sid-8C08A459-CCB4-4F0C-AC81-C12C47C42B9C" sourceRef="sid-39AAD947-3626-4B45-8DCF-4D07636B76B1" targetRef="sid-DEA02220-00E9-44E6-B5D2-0A81B5E891F3"/>
    <endEvent id="sid-00CDB872-41BC-4BE0-A3A6-DBBCB476AC03"/>
    <sequenceFlow id="sid-92BB0878-F420-4BD1-90E6-B017AC44BC71" sourceRef="sid-DEA02220-00E9-44E6-B5D2-0A81B5E891F3" targetRef="sid-00CDB872-41BC-4BE0-A3A6-DBBCB476AC03"/>
  </process>
</code>

And below are my java delegates
<code>
@Component
public class ContactPickerTaskDelegation implements JavaDelegate {
    private Expression contactPickerRuleId;

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {
        List<Contact> contacts =  doStuff(contactPickerRuleId.getValue(delegateExecution).toString());
        delegateExecution.setVariable("contacts", contacts); 
    }
}


@Component
public class FealtiEmailTaskDelegation implements JavaDelegate {
    private Expression emailTemplateId;

    @Override
    public void execute(DelegateExecution delegateExecution) throws Exception {

        Contact contact = (Contact) delegateExecution.getVariable("contact");
        sendEmail(contact, emailTemplateId.getValue(delegateExecution).toString());
    }
}
</code>

Suggest me where I am doing wrong.

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Babji,

Complete jUnit test could help.
https://forums.activiti.org/content/sticky-how-write-unit-test

Regards
Martin

Hi Martin,

Thanks for the replay.
I followed the same link to write the test cases.

But in by case, I am using Spring-boot activiti integration.
I am not able to proceed further with the Unit Test Case provided (not able to load spring beans).

Please find below exception
<code>
org.activiti.engine.ActivitiException: Unknown property used in expression: ${contactPickerTaskDelegation}

at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:53)
</code>

Regards,
Babji.

warper
Star Contributor
Star Contributor
Hi Babji!
Looks like you did not include delegate classes into Spring context.
Your spring context configuration xml should contain lines like this:

<context:annotation-config />
<context:component-scan base-package="company.a.b.c.**" />
Instead of "company.a.b.c" you put base package for delegate classes.

Hi Warper,

I have java based configuration,
And I have included the base path of the application properly. (Since I am able to run the application properly, I can say my configuration is proper only)

If I am not wrong, in the provide test case template we are not loading complete spring (spring-boot) application.
<code>
public class MyUnitTest {
@Rule
public ActivitiRule activitiRule = new ActivitiRule();

@Test
@Deployment(resources = {"org/activiti/test/my-process.bpmn20.xml"})
public void test() {
  ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
  assertNotNull(processInstance);
 
  Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
  assertEquals("Activiti is awesome!", task.getName());
}
}
</code>

Since we are not loading the spring context, activiti is not able to resolve the spring bean.
could you please guide me how can i write test case in this case.

warper
Star Contributor
Star Contributor
Hi Babji!
My unit tests are based on private class that extends SpringActivitiTestCase (package org.activiti.spring.impl.test).
Unit tests are done through junit and mockito and private class extensions, so they are way too different from your case.
Spring context is defined mostly in xml, each test class has @ContextConfiguration annotation with locations of specific test configurations.
Unfortunately I have no clean, simple and ready to share unit test.
Probably you can derive something starting from SpringActivitiTestCase.

jbarrez
Star Contributor
Star Contributor
${contactPickerTaskDelegation} needs to be the name of the bean you are exposing in your Spring Boot application and when running test, it needs to be on the classpath.