0
votes

I have written a batch apex class for case escalation. I want to write a Test class for it. Can someone please help me. Below is the code which i wrote:

global class CaseEscalation  implements  Database.Batchable<SObject> 

{

global CaseEscalation()

{

}  

 global Database.QueryLocator start(Database.BatchableContext  ctx)

 {

  System.debug('checking=======');

     return Database.getQueryLocator([SELECT  CaseNumber, CreatedDate,Status FROM Case             where (Status!='Closed' AND Status!='Escalated') and CreatedDate<TODAY ]); 

 }


 global void execute(Database.BatchableContext ctx, List<Sobject> scope)

 {

   List<Case> ca = (List<Case>)scope;

   System.debug('checking======='+ca);

   for(Case c : ca)

   {      

             System.Debug(c);
             String emailMessage = 'The case  ' + c.CaseNumber + ' has been ecalated ' + ' Please look into the case ' + 'Thankyou';

             Messaging.SingleEmailMessage mail  =   new Messaging.SingleEmailMessage();

             String[] toAddresses = new String[] {'[email protected]'};

             mail.setToAddresses(toAddresses);

             mail.setSubject('Case Escalation');

             mail.setPlainTextBody(emailMessage);

             Messaging.sendEmail(new Messaging.SingleEmailMessage[]{ mail });

             c.Status = 'Escalated';

    }

    if(ca.size()>0)

    update ca;

       }

global void finish(Database.BatchableContext ctx)

{

}


}
1

1 Answers

0
votes

You won't easily be able to test your batch with the code the way that it currently is. This is because when you create your test data it will be created with a created date of today and hence your query locator will not return any records and the execute method won't run.

I have tweaked your batch to make it workable.

global class CaseEscalation implements Database.Batchable<SObject> {

    private static Date cutOff;

    global CaseEscalation(Date CutOffDate){
        cutOff = CutOffDate;
    }  

    global Database.QueryLocator start(Database.BatchableContext  ctx){
        return Database.getQueryLocator('SELECT Id, CaseNumber, CreatedDate, Status FROM Case WHERE (Status != \'Closed\' AND Status != \'Escalated\') and CreatedDate < :cutOff '); 
    }

    global void execute(Database.BatchableContext ctx, List<Sobject> scope){

        if(scope.size() == 0)
            return;

        for(Case c : (List<Case>)scope){      
            String emailMessage = 'The case  ' + c.CaseNumber + ' has been ecalated ' + ' Please look into the case ' + 'Thankyou';
            Messaging.SingleEmailMessage mail  =   new Messaging.SingleEmailMessage();
            String[] toAddresses = new String[] {'[email protected]'};
            mail.setToAddresses(toAddresses);
            mail.setSubject('Case Escalation');
            mail.setPlainTextBody(emailMessage);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[]{ mail });

            c.Status = 'Escalated';
        }

        update scope;
    }

    global void finish(Database.BatchableContext ctx){

    }
}

Once you have this you can write some tests to prove that it runs. You need to be aware that you can't send more than 10 emails at a time from within a batch execute method so when executing the batch you must make sure you pass the scope parameter to the execute method. Having said that I would be very tempted to simply build up the body of the email within the loop in the execute method and then send one email with all of the details of the updated records in it - one email, a much cleaner inbox and no worries of hitting governor limits. I haven't done this as I wanted to keep it as close as possible to your original code.

You can then write a test script that looks like this to exercise the code.

@isTest
private class CaseEscalationTest {

    private static testMethod void testInCutOff(){

        List<Case> testCases = new List<Case>();

        for(Integer i = 0; i < 10; i++)
            testCases.add(new Case(Status='Open'));

        insert testCases;

        Test.startTest();

        CaseEscalation ce = new CaseEscalation(system.today().addDays(1));
        database.executeBatch(ce, 10);

        Test.stopTest();

        testCases = [SELECT Id FROM Case WHERE Status = 'Open'];

        system.assertEquals(0, testCases.size());

    }

    private static testMethod void testOUtOfCutOff(){

        List<Case> testCases = new List<Case>();

        for(Integer i = 0; i < 10; i++)
            testCases.add(new Case(Status='Open'));

        insert testCases;

        Test.startTest();

        CaseEscalation ce = new CaseEscalation(system.today());
        database.executeBatch(ce, 10);

        Test.stopTest();

        testCases = [SELECT Id FROM Case WHERE Status = 'Open'];

        system.assertEquals(10, testCases.size());

    }

}

Things to note in the tests are the use of Test.startTest() and Test.stopTest() this forces the batch to execute before continuing with the test thus giving you the chance to select the updated data out of the database and ensure it has be altered as you would expect. As I said before the 'database.executeBatch()` method needs to have the second parameter passed to it to limit the number of records in the scope - you could remove this by changing the structure of your execute method. The only other thing to note is that it's good practice to create more than one record for testing the batch but remember not to create more than one "scope's" worth as you can only have one execute method called from a test.