cancel
Showing results for 
Search instead for 
Did you mean: 

Completing user task in unit testing, async behavior

sor1
Champ in-the-making
Champ in-the-making
I have some unit tests in the same test class checking that a user task appears and completing it.
It was working perfectly but now I have set the first service task (before the user task) of my process to async=”true”.
So, I had to change the code of the tests to wait that the user task appears after calling a startProcessInstance:
public class MyProcessTest extends ActivitiTestCase
{
    private ProcessInstance startProcessInstance() throws InterruptedException
    {
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("MyProcessKey");
        Assert.assertNotNull(processInstance.getId());
        waitAndCompleteUserTask();
        waitForJobExecutorToProcessAllJobs(30000, 100);
        return processInstance;
    }

    private void waitAndCompleteUserTask() throws InterruptedException
    {
        boolean taskIsAssignedToUser = false;
        List<Task> taskList = taskService.createTaskQuery().taskAssignee("MyUser").list();
        int numberOfUserTask = (int) taskList.size();
        System.out.println("numberOfUserTask=" + numberOfUserTask);
        int timeout = 0;
        while ((numberOfUserTask == 0) && timeout < 10000)
        {
            taskList = taskService.createTaskQuery().taskAssignee("MyUser").list();

            numberOfUserTask = (int) taskList.size();
            System.out.println("numberOfUserTask=" + numberOfUserTask);

            if (numberOfUserTask == 1)
            {
                taskIsAssignedToUser = true;
            }
            Thread.sleep(300);
            timeout += 300;
        }

        assertTrue("No task was assigned to user", taskIsAssignedToUser);
        Task userTask = taskList.get(0);
        taskService.complete(userTask.getId());
    }

    @Test
    @Deployment(resources =
    {
        "MyPackage/MyProcess.bpmn20.xml"
    })
    public void testUserTaskInFirstCase() throws InterruptedException
    {
        //Init test conditions 1
        startProcessInstance();
        //Check result 1
    }

    @Test
    @Deployment(resources =
    {
        "MyPackage/MyProcess.bpmn20.xml"
    })
    public void testUserTaskInSecondCase() throws InterruptedException
    {
        //Init test conditions 2
        startProcessInstance();
        //Check result 2
    }

    /**
     * Wait no more jobs are in execution - useful for asynchronous behavior,
     * which is the case of our process.
     *
     * @param maxMillisToWait
     * @param intervalMillis
     */
    private void waitForJobExecutorToProcessAllJobs(long maxMillisToWait, long intervalMillis) throws InterruptedException
    {
        //The famous method…       
    }
}
If I execute each test separately, it works fine. But if I execute all the tests of the class, it works for the first test but it does not work for the second test: the user task is never found: I get an AssertionFailedError "No task was assigned to user". In fact, it seems the process has not even gone through the first service task as I cannot see the corresponding log.
In the activity.cfg.xml file, I have:
<property name="jobExecutorActivate" value="true" />
If I set:
<property name="jobExecutorActivate" value="false" />
It is worth: the 2 tests fail with the AssertionFailedError.
What’s wrong?
3 REPLIES 3

sor1
Champ in-the-making
Champ in-the-making
If I replace the runtimeService used to start the process by:
ProcessEngines.getDefaultProcessEngine().getRuntimeService();
in stead of the runtimeService proposed by the ActivitiTestCase my tests work.

Do you understand why?

frederikherema1
Star Contributor
Star Contributor
Not really getting the initial problem. Are you setting the jobExecutorActivate to FALSE? This makes sense the test fails, the async jobs will never be executed.

If you use ProcessEngines.getDefaultProcessEngine().getRuntimeService(), ANOTHER process-engine will be created, using activiti.cfg.xml on the class path (eg. src/main/resouces). If this contains an ACTIVE job-executor, it makes sense the tests run…

sor1
Champ in-the-making
Champ in-the-making
Thanks a lot,
I want to use jobExecutorActivate to TRUE (I have tried to use jobExecutorActivate to FALSE to see if it solves my problem, but now just forget this test)

To start the process, if I use runtimeService (of ActivitiTestCase) or ProcessEngines.getDefaultProcessEngine().getRuntimeService() in both cases the activiti.cfg.xml file used is in src/test/resources.
So in both case, the property jobExecutorActivate" value="true" is used.
So the reason why it work with ProcessEngines.getDefaultProcessEngine().getRuntimeService() is still unknown.