According to Salesforce docs:
All asynchronous calls made after the startTest method are collected by the system. When stopTest is executed, all asynchronous processes are run synchronously.
Now I was assuming this holds true for all async apex, but for the queueable apex, it executes even if we don't enqueue a job between start test and stop test.
Minimum Viable Code to reproduce:
Queueable Apex :
public class MyQueueableApex implements Queueable{
public void execute(QueueableContext context) {
System.debug('Inside Queueable apex');
}
}
Test class:
@isTest
public class MyQueueableApexTest {
@isTest
public static void queuableTest(){
Id jobId = System.enqueueJob(new MyQueueableApex());
System.assertNotEquals('Completed' , [SELECT Id , Status FROM AsyncApexJob WHERE Id=:jobId][0].Status);
}
}
Debug:
48.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;NBA,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WAVE,INFO;WORKFLOW,INFO
16:24:33.0 (404217)|USER_INFO|[EXTERNAL]|00528000000PIGY|pjxdsfse@gmail.com|(GMT+00:00) Greenwich Mean Time (Europe/London)|GMTZ
16:24:33.0 (445053)|EXECUTION_STARTED
16:24:33.0 (450671)|CODE_UNIT_STARTED|[EXTERNAL]|01p0I00000GAtQS|MyQueueableApexTest.queuableTest()
16:24:33.0 (11522220)|SOQL_EXECUTE_BEGIN|[8]|Aggregations:0|SELECT Id, Status FROM AsyncApexJob WHERE Id = :tmpVar1
16:24:33.0 (15845130)|SOQL_EXECUTE_END|[8]|Rows:1
16:24:33.16 (16115510)|CUMULATIVE_LIMIT_USAGE
16:24:33.16 (16115510)|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 1 out of 100
Number of query rows: 1 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 1 out of 50
Number of Mobile Apex push calls: 0 out of 10
16:24:33.16 (16115510)|CUMULATIVE_LIMIT_USAGE_END
16:24:33.0 (16157837)|CODE_UNIT_FINISHED|MyQueueableApexTest.queuableTest()
16:24:33.0 (17551568)|EXECUTION_FINISHED
16:24:33.27 (27032903)|USER_INFO|[EXTERNAL]|00528000000PIGY|pjxdsfse@gmail.com|(GMT+00:00) Greenwich Mean Time (Europe/London)|GMTZ
16:24:33.27 (27047994)|EXECUTION_STARTED
16:24:33.27 (27051597)|CODE_UNIT_STARTED|[EXTERNAL]|01p0I00000GAtQN|MyQueueableApex
16:24:33.27 (28544098)|USER_DEBUG|[3]|DEBUG|Inside Queueable apex
16:24:33.27 (28634595)|CODE_UNIT_FINISHED|MyQueueableApex
16:24:33.27 (29986879)|EXECUTION_FINISHED
The status of async-apex job is still Pending, I can see from debug log. execute method was called even if I didn't use start , stop test at all. Is it expected behaviour documented somewhere?
The issue I faced is, I was unit-testing if queueable is being queued with dummy value, I didn't care about if it was successful or not, but my unit test broke cause Apex Test execute queueabale, and due to dummy values, SOQL failed.
Also this document states:
The ID of a queueable Apex job isn’t returned in test context—System.enqueueJob returns null in a running test.
I could still see enqueueJob returning proper job id and not null.