function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jaap ScheperJaap Scheper 

Test - Schedulable class does not run after Test.Stoptest()

Hi all,

I am trying to test a Schedulable class that invokes an @future(Callout=true) method called runWarehouseEquipmentSync.
After Test.StopTest() I check whether the Schedulable already has been triggered (I expect so). It has not been triggered yet.

Can you explain why the Schedulable class not have been triggered after Test.StopTest()?
How do I test the Schedulable class in a correct manner?
 
@IsTest
public with sharing class WarehouseSyncScheduleTest {
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';

    @IsTest
    public static void testScheduledJob() {
        WarehouseCalloutServiceMock mock = new WarehouseCalloutServiceMock();
        Test.setMock(HttpCalloutMock.class, mock);

        // 1. Create data
        List<Product2> equipmentsBefore = [SELECT Id FROM Product2];
        System.AssertEquals(0, equipmentsBefore.size());

        // 2. Schedule a job and run it
        Test.StartTest();
            String jobId = System.Schedule('ScheduledApexTest',
                CRON_EXP,
                new WarehouseSyncSchedule());
            System.Debug('Scheduler JobId: ' + jobId);

            CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
            System.assertEquals(CRON_EXP, ct.CronExpression);
            System.assertEquals(0, ct.TimesTriggered);
            System.assertEquals('2022-03-15 00:00:00', String.valueOf(ct.NextFireTime));
        Test.StopTest();

        ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
        System.assertEquals(CRON_EXP, ct.CronExpression);
        System.assertEquals(1, ct.TimesTriggered); //Test fails here: ct.TimesTriggered is still 0!
        System.assertEquals('2022-03-15 00:00:00', String.valueOf(ct.NextFireTime));

        // 3. Get data and verify that it has changed due to the scheduler
        List<Product2> equipmentsAfter = [SELECT Id FROM Product2];
        System.AssertEquals(2, equipmentsAfter.size());
    }
}

This is the WarehouseSyncSchedule method:
global class WarehouseSyncSchedule implements Schedulable {
  global void execute(SchedulableContext sc) {
      System.Debug('I am here at WarehouseSyncSchedule!'); //I see this code in the output log: so far so good.
      WarehouseCalloutService.runWarehouseEquipmentSync();
  }
}
This is the runWarehouseEquipmentSync():
@future(Callout=true)
    public static void runWarehouseEquipmentSync(){
        //Implementation - removed for readability
        //I do not see any debug statement in the output/log window for this method
    }


 
Jaap ScheperJaap Scheper
Hi Amit,
Thank you, I didnt find that post. There seems to be odd Salesforce behavior causing the TimesTriggered not to be incremented after the StopTest().

I am still confused why the @future method runWarehouseEquipmentSync() does not seem to be executed. I am still missing something here.
For now I solved it by firing the Scheduler's execute method manually from the testcase.
Better suggestions are welcome! :)
 
@IsTest
public with sharing class WarehouseSyncScheduleTest {
    public static String CRON_EXP = '0 0 0 15 3 ? 2022';

    @IsTest
    public static void testScheduledJob() {
        WarehouseCalloutServiceMock mock = new WarehouseCalloutServiceMock();
        Test.setMock(HttpCalloutMock.class, mock);

        // 1. Create data
        List<Product2> equipmentsBefore = [SELECT Id FROM Product2];
        System.AssertEquals(0, equipmentsBefore.size());

        // 2. Schedule a job and run it
        Test.StartTest();
            String jobId = System.Schedule('ScheduledApexTest',
                CRON_EXP,
                new WarehouseSyncSchedule());
            System.Debug('Scheduler JobId: ' + jobId);

            // 3. Verify that the job was added correctly
            CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId];
            System.assertEquals(CRON_EXP, ct.CronExpression);
            System.assertEquals(0, ct.TimesTriggered);
            System.assertEquals('2022-03-15 00:00:00', String.valueOf(ct.NextFireTime));

            // 4. WarehouseSyncSchedule.execute() is supposed to invoke WarehouseCalloutService.runWarehouseEquipmentSync()
            // It looks like this invocation does not happen after Test.Stoptest() (although WarehouseSyncSchedule.execute() is being executed!)
            // Invoking WarehouseSyncSchedule.execute manually here, does invoke WarehouseCalloutService.runWarehouseEquipmentSync()
            // Don't you understand this? Me neither.
            WarehouseSyncSchedule schedulable = new WarehouseSyncSchedule();
            System.SchedulableContext sc = null;
            schedulable.execute(sc);
        Test.StopTest();

        // 5. Get data and verify that it has changed due to the scheduler
        List<Product2> equipmentsAfter = [SELECT Id FROM Product2];
        System.AssertEquals(2, equipmentsAfter.size());
    }
}