[SalesForce] How to test Batch apex that executes another batch job

I have a batch job that does the following :

  • Makes Http callout
  • Create Cases
  • Calls the next Batch job (In the finish function) i.e.

Batch

public void finish(Database.BatchableContext context) {
    if (LOG_THIS_CLASS) System.debug('<Arcus> In the finish function of CaseCreation class.. ');

    AsyncApexJob batchJob = [
        SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email
        FROM AsyncApexJob
        WHERE Id = :context.getJobId()
    ];

    Integer jobs = [
        SELECT COUNT() 
        FROM AsyncApexJob 
        WHERE JobType = 'Batch Apex' 
        AND Status IN ('Queued', 'Processing', 'Preparing')
    ];
    Integer scopeSize = Limits.getLimitCallouts() - Limits.getCallouts();
    System.debug('<Arcus> The scope size == ' + scopeSize);
    if (jobs > 4) {
        // try again in a minute
        Datetime sysTime = System.now().addSeconds(60);
        String chronExpression = '' + sysTime.second() + ' ' + sysTime.minute() + ' ' + sysTime.hour() + ' ' + sysTime.day() + ' ' + sysTime.month() + ' ? ' + sysTime.year();

        CaseScheduler scheduledBatch = new CaseScheduler();
        System.scheduleBatch(new AccountCaseLink(), 'Case Account Link' + sysTime, 1, scopeSize);                
    } else {
        AccountCaseLink batch = new AccountCaseLink();
        Database.executeBatch(batch, scopeSize);
    }
}

The second batch job does another http callout based on the ids of the cases created and does account matching for each case.
To test this, I have created a HttpCalloutMock and just set the mock in my test class. When tested I get error : System.NullPointerException: Attempt to de-reference a null object. Any help? Thanks

Best Answer

When you have a batch finish() launch a second batch via executeBatch(), you must use two testmethods:

  1. Testmethod 1 - tests the first batch start-execute-finish sequence
  2. Testmethod 2 - tests the second batch start - execute - finish sequence as if it had been launched by the first batch's finish().

SFDC won't actually execute a batch in a testmethod until the Test.stoptest() is reached and you won't be able to assert the results of batch 2.

Testing batches with http callouts and setup of test data requires testing start(), execute(), and finish() explicitly if you get an Uncommitted Work pending error. See here and here.

Related Topic