AnsweredAssumed Answered

Asynchronous User Task and Mocks

Question asked by jwglista on Sep 7, 2016
Latest reply on Sep 8, 2016 by jwglista
Hello,

I've had success using the MockExpressionManager to mock delegate methods for Service Tasks, as well as task listeners.  I have a user task that is asynchronous, and I am attempting to mock a listener method on this user task for the create event.  From my understanding, this requires the use of JobTestHelper.waitForJobExecutorToProcessAllJobs so that the asynchronous user task can complete before verifying any of the mocks or other behavior.  However, I'm finding that when using this method, the Activiti Engine can not resolve the mocked object, even though it has been registered with the MockExpressionManager using the Mocks.register() method.

Does anyone have any suggestions on this?

Thanks

<b>Java Test class (snippet):</b>

   @Mock
   private TestMockDelegate testMockDelegateMock;
   
   @Mock
   private TestMockListener testMockListenerMock;

   @Before
   public void setup() throws Exception {
      MockitoAnnotations.initMocks(this);
      SpringProcessEngineConfiguration configuration = (SpringProcessEngineConfiguration) processEngine.getProcessEngineConfiguration();
      configuration.setExpressionManager(new MockExpressionManager());
   }

   @Test
   public void testWithMock() throws Exception {
      System.out.println("================= testWithMock() start =================");
      Mocks.register("testMockDelegate", testMockDelegateMock);
      Mocks.register("testMockListener", testMockListenerMock);
      when(testMockDelegateMock.execute((DelegateExecution) anyObject())).thenReturn("mock execute() was used");
      ProcessInstance pi = runtimeService.startProcessInstanceByKey("testMockProcess");
      assertNotNull(pi);
      
      JobTestHelper.waitForJobExecutorToProcessAllJobs(processEngine.getProcessEngineConfiguration(), managementService, 10000L, 100L);
      
      verify(testMockDelegateMock, times(1)).execute((DelegateExecution) anyObject());
      verify(testMockListenerMock, times(1)).execute((ActivityExecution) anyObject());
      verify(testMockListenerMock, times(1)).notify((DelegateTask) anyObject());
      verifyNoMoreInteractions(testMockDelegateMock);
      verifyNoMoreInteractions(testMockListenerMock);
      System.out.println("================= testWithMock() end  ================= \n");
   }


<b>User task as defined in the process definition:</b>

    <userTask id="usertask1" name="User Task" activiti:async="true">
      <extensionElements>
        <activiti:taskListener event="create" expression="${testMockListener.notify(task)}"></activiti:taskListener>
      </extensionElements>
    </userTask>


<b>The listener class:</b>

public class TestMockListener {
   
   private static final Logger log = Logger.getLogger(TestMockListener.class);
   
   public void notify(DelegateTask task)  {
      System.out.println("TestMockListener.notify() has been executed");
   }
   
   public void execute(ActivityExecution execution) {
      System.out.println("TestMockListener.execute() has been executed");
   }
}


<b>The exception: </b>

================= testWithMock() start =================
mock execute() was used
2016-09-07 08:18:45 ERROR ExecuteJobsRunnable:96 - exception during job execution: Job 45 failed
org.activiti.engine.ActivitiException: Job 45 failed
   at org.activiti.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:110)
   at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24)
   at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:57)
   at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47)
   at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
   at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45)
   at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40)
   at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35)
   at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.handleMultipleJobs(ExecuteJobsRunnable.java:94)
   at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:49)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
   at java.lang.Thread.run(Thread.java:745)
Caused by: org.activiti.engine.ActivitiException: Exception while invoking TaskListener: Unknown property used in expression: ${testMockListener.notify(task)}
   at org.activiti.engine.impl.persistence.entity.TaskEntity.fireEvent(TaskEntity.java:742)
   at org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior.execute(UserTaskActivityBehavior.java:213)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationActivityExecute.execute(AtomicOperationActivityExecute.java:60)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:655)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:650)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(AtomicOperationTransitionNotifyListenerStart.java:52)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:56)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:655)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:650)
   at org.activiti.engine.impl.pvm.runtime.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:655)
   at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:650)
   at org.activiti.engine.impl.pvm.runtime.AtomicOperationTransitionCreateScope.execute(AtomicOperationTransitionCreateScope.java:49)
   at org.activiti.engine.impl.interceptor.CommandContext.performOperation(CommandContext.java:97)
   at org.activiti.engine.impl.jobexecutor.AsyncContinuationJobHandler.execute(AsyncContinuationJobHandler.java:35)
   at org.activiti.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:85)
   at org.activiti.engine.impl.persistence.entity.MessageEntity.execute(MessageEntity.java:34)
   at org.activiti.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:88)
   … 13 more
Caused by: org.activiti.engine.ActivitiException: Unknown property used in expression: ${testMockListener.notify(task)}
   at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:53)
   at org.activiti.engine.impl.bpmn.listener.ExpressionTaskListener.notify(ExpressionTaskListener.java:33)
   at org.activiti.engine.impl.delegate.TaskListenerInvocation.invoke(TaskListenerInvocation.java:34)
   at org.activiti.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:37)
   at org.activiti.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:25)
   at org.activiti.engine.impl.persistence.entity.TaskEntity.fireEvent(TaskEntity.java:738)
   … 33 more
Caused by: org.activiti.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier 'testMockListener'
   at org.activiti.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:83)
   at org.activiti.engine.impl.juel.AstMethod.invoke(AstMethod.java:90)
   at org.activiti.engine.impl.juel.AstMethod.eval(AstMethod.java:86)
   at org.activiti.engine.impl.juel.AstEval.eval(AstEval.java:50)
   at org.activiti.engine.impl.juel.AstNode.getValue(AstNode.java:26)
   at org.activiti.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)
   at org.activiti.engine.impl.delegate.ExpressionGetInvocation.invoke(ExpressionGetInvocation.java:33)
   at org.activiti.engine.impl.delegate.DelegateInvocation.proceed(DelegateInvocation.java:37)
   at org.activiti.engine.impl.delegate.DefaultDelegateInterceptor.handleInvocation(DefaultDelegateInterceptor.java:25)
   at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:48)
   … 38 more

Outcomes