Thursday, 30 August 2012

Adding a Test for the Schedulable Class - Apex

Prerequisites:
  • Tutorial #12: Apex Unit Tests
Now that you’ve added a schedulable class, you’ll also need to add a test method to ensure that your class has test coverage. In this lesson, you’ll add a test class with one test method, which calls System.Schedule to schedule the class.
You’ll switch to the Apex Classes page to create the test class since you’ll be running the tests from there.
  1. Click Your Name | Setup | Develop | Apex Classes | New.
  2. In the code editor box, add the following test class.
    @isTest
    private class TestSchedulableClass {
    
       // CRON expression: midnight on March 15. 
        
       // Because this is a test, job executes 
        
       // immediately after Test.stopTest(). 
        
       public static String CRON_EXP = '0 0 0 15 3 ? 2022';
    
       static testmethod void test() {
          Test.startTest();
    
          // Schedule the test job 
        
          String jobId = System.schedule('ScheduleApexClassTest',
                            CRON_EXP, 
                            new MySchedulableClass());
             
          // Get the information from the CronTrigger API object 
        
          CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, 
             NextFireTime
             FROM CronTrigger WHERE id = :jobId];
    
          // Verify the expressions are the same 
        
          System.assertEquals(CRON_EXP, 
             ct.CronExpression);
    
          // Verify the job has not run 
        
          System.assertEquals(0, ct.TimesTriggered);
    
          // Verify the next time the job will run 
        
          System.assertEquals('2022-03-15 00:00:00', 
             String.valueOf(ct.NextFireTime));
          // Verify the scheduled job hasn't run yet. 
        
          Merchandise__c[] ml = [SELECT Id FROM Merchandise__c 
                                 WHERE Name = 'Scheduled Job Item'];
          System.assertEquals(ml.size(),0);
          Test.stopTest();
    
          // Now that the scheduled job has executed after Test.stopTest(), 
        
          //   fetch the new merchandise that got added. 
        
          ml = [SELECT Id FROM Merchandise__c 
                                 WHERE Name = 'Scheduled Job Item'];
          System.assertEquals(ml.size(), 1);
    
       }
    }
  3. Click Save.
  4. Click Run Test to execute the test method.

Tell Me More...

  • The test method schedules the MySchedulableClass class by calling the System.schedule method. The System.Schedulemethod takes three arguments: a name for the job, an expression used to represent the time and date the job is scheduled to run, and the name of the class. The System.schedule method uses the user's timezone for the basis of all schedules.
  • The call to System.schedule is included within the Test.startTest and Test.stopTest block. This ensures that the job gets executed after the Test.stopTest call regardless of the schedule specified in the cron expression. Any asynchronous code included within Test.startTest and Test.stopTest gets executed synchronously after Test.stopTest.
  • Finally, the test method verifies a new merchandise item got added by the scheduled class.
Tip

  • The System.Schedule method uses the user's timezone for the basis of all schedules.
  • You can only have 25 classes scheduled at one time.

3 comments:

  1. You say to use Test.startTest() and Test.stopTest() methods to wrap the call System.schedule() and that this cause the job to run. I tried this to test scheduling my job to send email. After the Test.stopTest() my job was still in the "WAITING" state. Here is my code:
    @isTest
    private class SendReminderEmailScheduleTest {


    static testmethod void test() {
    Test.startTest();
    // create a CRON schedule string
    Datetime dt = Datetime.now().addMinutes(1);
    String cron_schedule = '0 '+dt.minute()+' * '+dt.day()+' '+dt.month()+' ? '+dt.year();

    // ask the system to create a job by scheduling our Appointment Reminder class
    String jobId = System.schedule('SendReminderEmailScheduleTest',
    cron_schedule,
    new SendReminderEmailSchedule());

    // Get the CronTrigger object for our job
    CronTrigger ct = [SELECT Id, TimesTriggered, State FROM CronTrigger WHERE id = :jobId];

    // Verify the job has not run
    System.assertEquals(0, ct.TimesTriggered);
    System.assertEquals('WAITING', ct.State);

    // As we created the job while in "test mode," calling "stopTest()" will cause the job to run
    Test.stopTest();

    // Get the CronTrigger object for our job (again)
    ct = [SELECT Id, TimesTriggered, State FROM CronTrigger WHERE id = :jobId];

    // Verify the job has run
    System.assertEquals(1, ct.TimesTriggered);
    System.assertEquals('COMPLETE', ct.State);

    // Is there some additional assert we can run to know the system has sent the emails?
    }
    }


    The System.assertEquals(1, ct.TimesTriggered); FAILS with ct.TimesTriggered == 0

    ReplyDelete
  2. Articles, on the other hand, can vary greatly in length depending on the publication and the topic at hand. Will Gojo Satoru Die In Jujutsu Kaisen? They can range from a few hundred to several thousand words, allowing for more in-depth exploration of complex subjects.

    ReplyDelete