2

I have a Schedulable APEX class that applies System.abortJob() on multiple CronTrigger.

I need to cover in test this method but I am afraid of the behaviour:

  • In a Test context, how is the CronTrigger table ?
  • If it is shared with non test context, will the job aborting be rollbacked outside the test context ?

UPDATE: code example

global ScheduledCronDelete implements Schedulable {

  global void execute(ScheduleContext context) {

    for (CronTrigger job: [
      SELECT Id, State, CronjobDetail.Name, CronJobDetail.Id, NextFireTime
      FROM CronTrigger
      WHERE NextFireTime = NULL
      AND CronJobDetail.Name LIKE 'CronJobNameToDelete%'
    ]) {
      System.abortJob(job.Id);
    }

  }
}

How can I do APEX tests over this ?

5
  • It won't affect other jobs since you're passing a JobId which you've created in your test class. Also go through this article May 5, 2017 at 8:54
  • Ok thank you. It is harder than that because I am not creating and deleting specific type inside my test. The function I want to test daily delete every CronTrigger with a specific prefix in its name and a specific status.
    – Simonp
    May 5, 2017 at 13:21
  • Update post with example of code
    – Simonp
    May 7, 2017 at 16:39
  • 1
    What is it you think would cause NextFireTime to be null? I don't think I've ever seen that scenario arise but maybe I'm just naive?
    – Adrian Larson
    May 7, 2017 at 17:30
  • No, it doesn't affect your already scheduled jobs outside of the test context!
    – Bahman.A
    Apr 8, 2021 at 16:51

1 Answer 1

3

To write any Apex Job always remember to create one helper method that will contain your Job logic. Call helper method from execute method by passing appropriate parameters. Why I'm recommending this because it will keep your code modularize and easy to test it. Specially from test class.

Also when you deploy your code to client side, imagine how your clients are going to test your Apex Job. You should not expect that they will go to developer console to schedule your job and wait until your job gets executed (specially if your Job will execute after 1 month). Am I right?. So having helper method is always a good practice. You can build VF page and simply invoke helper method to show how your Job will run without the need of scheduling a Apex job.

I've restructured your Apex Job so that it is convenient to test it and incorporates above point which I mentioned.

Apex Job

global class ScheduledCronDelete implements Schedulable {

    global ScheduledCronDelete () {

    }
    global void execute(SchedulableContext sc) {
        // passing null since it's a legitimate call from Apex Job and 
        // not from test class or any VF page
        helperMethod(null);
    }
    public void helperMethod(String jobName) {
        List<CronTrigger> lstJobs = new List<CronTrigger>();
        String query = 'SELECT Id, State, CronjobDetail.Name, CronJobDetail.Id, NextFireTime FROM CronTrigger WHERE ';
        // if jobName is null then it is invoke from execute class
        if(jobName == NULL) {
            String name = 'CronJobNameToDelete%';
            query = query + ' CronJobDetail.Name LIKE \''+name+'\'';

        } else {
            // it's a simple use case for testing purpose
            query = query + ' CronJobDetail.Name LIKE \''+jobName+'%\'';
        }
        System.debug(query);
        lstJobs = Database.query(query);

        if(lstJobs.size() > 0) {
            for (CronTrigger job : lstJobs)
                System.abortJob(job.Id);
        }
    }
}

Test Class

@isTest
public class JobTest {
    static @isTest void myTest () {
        test.startTest();
            String hour = String.valueOf(Datetime.now().hour());
            String min = String.valueOf(Datetime.now().minute() + 1); String ss = String.valueOf(Datetime.now().second());

            //parse to cron expression
            String nextFireTime = ss + ' ' + min + ' ' + hour + ' * * ?';
            ScheduledCronDelete s = new ScheduledCronDelete(); 
            System.schedule('CronJobNameToDelete' + String.valueOf(Datetime.now()), nextFireTime, s);

            System.schedule('TestJob' + String.valueOf(Datetime.now()), nextFireTime, s);
            String jobName = 'TestJob';
            s.helperMethod(jobName);
        test.stopTest();
    }
}

Above test class will give you 100% code coverage.

And your doubts:

  1. In a Test context, how is the CronTrigger table ? --> It doesn't affect your already schedule Jobs. I tried it and it didn't affected existing job. Give it a try.

  2. If it is shared with non test context, will the job aborting be rollbacked outside the test context ? --> Once you try for point 1 you will eventually get the answer for this question.

6
  • Any reason why my answer got downvoted? May 8, 2017 at 5:52
  • @AdrianLarson @Rohit The case when NextFireTime is NULL is when you Schedulable job implements Batchable as well. So the scheduled job is fired one and only one time. So this condition is logical in my context. Thank you for the Helper function, I haven't thaught about it. PS: Sorry for the downvote, I missclicked and I have to wait to cancel it.
    – Simonp
    May 8, 2017 at 6:24
  • Ok. So Is that answer to your question correct? May 8, 2017 at 6:26
  • @SimonPlacentino So I guess you can remove that downvote and accept the answer May 8, 2017 at 6:27
  • you have to edit your post to do so
    – Simonp
    May 8, 2017 at 6:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .