[SalesForce] Apex test class for schedulable class that checks for 5 batches running already

I've setup some chain execution batch classes. For this setup we decided to chain the batch classes through schedulable classes. We thought it might be a good idea to include a check for 5 batch jobs running so we didn't hit the concurrent batch processing limit. Here's the method we put into our schedulable classes:

global class Schedule_Batch implements Schedulable {
  global void execute(SchedulableContext sc) {            
    MyBatch b = new MyBatch();

    //check if there are 5 active batch jobs
    if([Select count() FROM AsyncApexJob WHERE JobType='BatchApex' AND(Status = 'Processing' OR Status = 'Preparing')]<5){
        Database.executebatch(b);
    }else{
        //schedule this same class again in 30 minutes
        Schedule_Batch bagain = new Schedule_Batch();
        Datetime dt = Datetime.now() + (0.024305); // i.e. 30 mins
        String timeForScheduler = dt.format('s m H d M \'?\' yyyy');
        Id schedId = system.Schedule('CFP_TaskBatch_Retry'+timeForScheduler,timeForScheduler,bagain);
    }
  } 
}   

This was taken from the developer forums – http://help.salesforce.com/apex/HTViewSolution?id=000182449&language=en_US.

The problem is unit testing. I've not been able to get to the else part of the if statement that finds at least five concurrent jobs running. Would someone please help me to test out 5 concurrent batch jobs running so I can have full coverage for the schedulable class? Here's the relevant part of my test class that I'm trying so far:

MyBatch b = new MyBatch();        
Id BatchprocessId = Database.executeBatch(b);

MyBatch b2 = new MyBatch();      
Id BatchprocessId2 = Database.executeBatch(b2);

MyBatch b3 = new MyBatch();       
Id BatchprocessId3 = Database.executeBatch(b3);

MyBatch b4 = new MyBatch();            
Id BatchprocessId4 = Database.executeBatch(b4);

MyBatch b5 = new MyBatch();      
Id BatchprocessId5 = Database.executeBatch(b5);        

Schedule_Batch q = new Schedule_Batch();
SchedulableContext scq;
q.execute(scq);  

Best Answer

You're going to have to fake it. What I do in situations like this is create a property with a getter and setter, but where the setter can only be used in tests.

As an example, setup a new property:

public static Integer runningJobCount{
    get{
        if(runningJobCount == null)
            return [Select count() FROM AsyncApexJob WHERE JobType='BatchApex' AND(Status = 'Processing' OR Status = 'Preparing')];
        else
            return runningJobCount;
    }
    set{
        System.assert(Test.isRunningTest(),'This property may only be set in tests');
        runningJobCount = value;
    }
}

Then change this line:

    if([Select count() FROM AsyncApexJob WHERE JobType='BatchApex' AND(Status = 'Processing' OR Status = 'Preparing')]<5){

to

    if(runningJobCount <5){

Then in your test you can set *Schedule_Batch.runningJobCount = 5;* in the test you want to test this scenario.

Related Topic