I am trying to write a unit test (junit4) to test a boundary timer will take me to the next expected task following the time reached. I have used the ProcessEngineConfig to set the process engine clock forward so that timer should fire. However, the timer does not seem to fire. I assume that the job has not fired when I test to see if next task has been reached. So is there support for testing timers.
Hey, I’m also trying to test a BPMN with a timer in it. So I tried to use suggestion above.
The timer is fired and the service task following the timer is executed on calling
but the job execution method throws OptimisticLockingException
managementService.executeJob(jobAway.getId());
When I remove the last call I guess the test is not thread safe anymore because sometimes the asserts I wrote for the process state fail.
I tried to use the PluggableFlowableTestCase but I’m testing in a Spring Boot environment and I did not manage to get the test case working together with @SpringBootTest.
we get an FlowableOptimisticLockingException. We added an event listener to find out what is happing. It seems that the call of executeJob(…) will execute the job twice: in the main thread and in the executor thread - followed by the FlowableOptimisticLockingException.
2019-04-23 08:33:31.139 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [startEvent1]
2019-04-23 08:33:31.141 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [sid-589E06DD-ADE0-407B-8AAE-33CCF24C17AC]
Current date and time: Tue Apr 23 08:33:31 CEST 2019
2019-04-23 08:33:31.455 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [printTimeBefore]
2019-04-23 08:33:31.455 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [sid-DDADF96E-3CB7-4731-B585-24BC278F73A2]
2019-04-23 08:33:31.519 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [waitTimer]
2019-04-23 08:33:31.519 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [sid-6BED58FA-0D97-4126-B07B-70CCD82B2F08]
2019-04-23 08:33:31.520 INFO H --- [ecutor-thread-1] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [waitTimer]
2019-04-23 08:33:31.520 INFO H --- [ecutor-thread-1] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [sid-6BED58FA-0D97-4126-B07B-70CCD82B2F08]
Date and time after timer: Tue Apr 23 08:33:31 CEST 2019
2019-04-23 08:33:31.532 INFO H --- [ecutor-thread-1] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [printTimeAfter]
2019-04-23 08:33:31.532 INFO H --- [ecutor-thread-1] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [flow1]
2019-04-23 08:33:31.533 INFO H --- [ecutor-thread-1] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [endevent1]
Date and time after timer: Tue Apr 23 08:33:31 CEST 2019
2019-04-23 08:33:31.537 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [printTimeAfter]
2019-04-23 08:33:31.537 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [flow1]
2019-04-23 08:33:31.538 INFO H --- [ main] c.a.s.p.t.t.TriggerTimerTest - {} : [5] [longRunningTimerProcess:1:4] [endevent1]
org.flowable.common.engine.api.FlowableOptimisticLockingException: Execution[ id '6' ] - activity 'endevent1' - parent '5' was updated by another transaction concurrently
at org.flowable.common.engine.impl.db.DbSqlSession.flushUpdates(DbSqlSession.java:505)
at org.flowable.common.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:292)
Different combinations of async and exclusive did not change the behaviour. If the test just waits for the one second, everything works fine. If we remove the executeJob(…) call, also no exception.
Is it intendend that the timer job is picked up twice?
When calling the moveTimerToExecutableJob method you get back a job instance which should be used to call the executeJob method instead of the original timer job id.
Ok thanks, did you disable the async executor in your process engine configuration? Because otherwise that async executor will try to execute the job after calling the moveTimerToExecutableJob method as well as your manual call to executeJob.
As we want to test our processes like in production environment, changing the config is not the best approach as the asyncExecutor will be needed. Furthermore, not every timer should be triggered manually. Sometimes timers should be triggered just by running into the defined due date.
Maybe you could mention the coincidence of asyncExecutor and executeJob(…) somewhere.
What is the consequence of using just moveTimerToExecutableJob(…) without calling executeJob(…)?
We solved this problem by setting the date/time of the whole process engine later than the expected due date.
Yes I understand. Moving the clock can be used to trick the async executor to not pick up the job yet, which is fine for a unit test. Another solution would be to indeed only call the moveTimerToExecutableJob method and then do a thread sleep for 5 seconds or so. Then the async executor should have fetched the job and executed it as well.