EDIT for clarification of title:
CronTrigger is probably actually firing at some point in the testing process – what is wierd is that CronTrigger.TimesTriggered is NOT incrementing after Test.stopTest()
Any asynchronous calls made within the Test.startTest()
and Test.stopTest()
methods of a test class should execute upon hitting Test.stopTest()
.
So, presumably, if I schedule a class using System.schedule()
, the CronTrigger object representing that scheduled job should fire immediately upon Test.stopTest()
, regardless of CronTrigger.NextFireTime
's value.
Here is my schedulable class:
global class Schedulable_Nightly implements Schedulable {
//PREDEFINED_SCHEDULE = "Every day at midnight"
public static String PREDEFINED_SCHEDULE = '0 0 0 * * ?';
global void execute(SchedulableContext SC) {
Database.executeBatch(new ContractTimelineBatch());
}
}
And here is my test method, pretty much lifted from SF documentation:
private class TestContractTimelineBatch {
@isTest static void test_schedulable(){
Test.startTest();
// Schedule the test job
String jobId = System.schedule('testBasicScheduledApex',
Schedulable_Nightly.PREDEFINED_SCHEDULE,
new Schedulable_Nightly());
// Get the information from the CronTrigger API object
CronTrigger ct = [SELECT Id, CronExpression, CronJobDetailId, CronJobDetail.Name, TimesTriggered, PreviousFireTime, NextFireTime, State
FROM CronTrigger WHERE id = :jobId];
// Verify the job has not run
System.assertEquals(0, ct.TimesTriggered);
Test.stopTest();
ct = [SELECT Id, CronJobDetailID, TimesTriggered, PreviousFireTime, NextFireTime, State
FROM CronTrigger WHERE id = :jobid];
//DEBUG STATEMENT SHOWS THAT ct.TimesTriggered IS STILL 0
system.debug('Cron - post: ' + ct);
// Verify that the job has now run
System.assertEquals(1, ct.TimesTriggered);
}
}
This final assertEquals fails because ct.TimesTriggered
stays at 0, both before and after Test.stopTest
What gives?
Best Answer
You could take a different approach to your test method
Instead of asserting whether the
schedulable
class was, in fact, executed, you should be asserting whether the schedulable'sexecute()
method actually did anything and what you expected. Testing that SFDC can schedule/execute aschedulable
per itsCronTrigger
proves nothing - as SFDC is guaranteed to execute your code at or around the time specified in the CronTrigger.In your case, whether the batch job processed the mocked sobjects is the interesting thing to test.