1

I am curious about how to test a scenario when a scheduled job throws an exception. Imagine this is how the schedulable class looks:

global class ExceptionScheduler implements Schedulable {   
    global void execute(SchedulableContext context) {         
            throw new InvalidVariableValueException();
        }
    }

In my test method, I schedule the job and try to catch all the exceptions to verify my exception is thrown after Test.stopTest() is executed. I tried something like this and the exception is thrown as it should be, but my try-catch does not catch it:

@isTest
static void exceptionIsThrown() {
    String jobName = 'ScheduledApexTest';
    String cronExp= '0 0 0 15 3 ? 2022';

    try{
        Test.startTest();
        System.schedule(jobName, cronExp, new ExceptionScheduler());
        Test.stopTest();
    }catch(Exception e){
        System.assertEquals(InvalidVariableValueException.getTypeName(), e.getTypeName());
    }
}

I guess that is because scheduled code runs asynchronously.

Is there another way to test this scenario and make sure my exceptions get thrown from scheduled code?

5

As we can assume that Salesforce test the System.schedule method so you don't have to, some or all of your test methods can directly invoke your Schedulable:

new ExceptionScheduler().execute(null);

though as AFAIK SchedulableContext can't be instantiated you'll need to pass null. Then the normal try/catch will work as its a synchronous call.

|improve this answer|||||
  • Thanks, in my case this is good enough, since I don't use the context in the body of my execute() method. I will leave the question open for some time to see if someone can find a solution that could work including the call to System.schedule() to preserve the context. – Andrej Lucansky Jan 29 '18 at 13:42
  • 5
    SchedulableContext is actually an interface, so you can implement it in a mock class if you do want to test against it. – IllusiveBrian Jan 29 '18 at 14:29
2

When stopTest() runs, it causes execution of any asynchronous calls made since startTest(), so there is guaranteed to be a finished AsyncApexJob record in your test's database. Unfortunately, it doesn't look like it has a single "exception" field, but you could check the Status, Extended Status or Number of Exceptions fields:

@isTest
static void exceptionIsThrown() {
    String jobName = 'ScheduledApexTest';
    String cronExp= '0 0 0 15 3 ? 2022';

    Test.startTest();
    ID jobID = System.schedule(jobName, cronExp, new ExceptionScheduler());
    Test.stopTest();

    System.assert([select ExtendedStatus from AsyncApexJob where ID = :jobID]
                         .ExtendedStatus.contains('InvalidVariableValueException'));
}
|improve this answer|||||
  • 1
    Yes, this could give me the exception to compare, but unfortunately, unless I somehow catch the exception as well and stop it from propagating, the test will still fail because the exception will break the execution and test will be reported as failed. – Andrej Lucansky Jan 29 '18 at 13:37
  • @AndrejLučanský Interesting, I didn't think the scheduled job failing would cause the test to fail. – IllusiveBrian Jan 29 '18 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.