[SalesForce] Test Class for Batch Apex Job

global class BatchApexDemo implements 
Database.Batchable<sObject>,Database.Stateful
{

    global integer recordProcessed = 0;
    global Database.QueryLocator start(Database.BatchableContext bc){
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new string[]{'ayz@gmail.com'}); 
        mail.setSenderDisplayName('Salesforce Admin');
        mail.setSubject('Processing has Started...');
        mail.setPlainTextBody('Batch processing has just Started...');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{
            mail
        });

        return Database.getQueryLocator(
            'SELECT Id, Name, BillingStreet, BillingCity,'+
            'BillingState, (SELECT MailingStreet, MailingCity, MailingState, FirstName, LastName FROM Contacts)'+
            'FROM Account'
        );
    }
    global void execute(Database.BatchableContext bc, List<Account> scope){
        List<Contact> con = new List<Contact>();
        for(Account acc : scope){
            for(Contact cont : acc.contacts){
                cont.MailingStreet = acc.BillingStreet;
                cont.MailingCity = acc.BillingCity;
                cont.MailingState = acc.BillingState;
                con.add(cont);
                recordProcessed = recordProcessed + 1;
            }
        }
        update con;
    }

    global void finish(Database.BatchableContext bc){
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setToAddresses(new String [] {
           'xyz@gmail.com' 
        });
        email.setPlainTextBody('Batch processing has been Completed for '+recordProcessed+' Records...');
        email.setSubject('Batch processing has done...');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
    }
}

Test class

@isTest
public class BatchApexDemo_Test {

    @isTest
    private static void WhenStartCalled_ShouldNotFail(){
        BatchApexDemo job = new BatchApexDemo();

        Test.startTest();
        job.start(null);
        Test.stopTest();

    }

    @isTest
    private static void WhenFinishedCalled_ShouldNotFail(){
        BatchApexDemo job = new BatchApexDemo();

        Test.startTest();
        job.finish(null);
        Test.stopTest();
    }

    @isTest
    private static void WhenExecuteCalled_ShouldUpdateTheContactRelatedToAccount(){

        Test.startTest();
        BatchApexDemo bd = new BatchApexDemo();
        List<Account> acc = new List<Account>{
            new Account(
                        Name= 'Test Account', 
                        BillingStreet= 'Street No 12', 
                        BillingCity= 'Pune', 
                        BillingState= 'MH'
                    )
                };
                insert acc;

        List<Contact> conn = new List<Contact>{
            new Contact(LastName= 'Test', 
                    FirstName= 'Test1', 
                    AccountId= acc[0].Id)
        };
        insert conn;
        List<Account> accc = [SELECT Id, Name, BillingStreet, BillingCity, BillingState FROM Account WHERE Id =: conn[0].AccountId Limit : 1];
        System.debug('Accounts in Test Class = '+accc);
        conn[0].MailingStreet = accc[0].BillingStreet;
        conn[0].MailingCity = accc[0].BillingCity;
        conn[0].MailingState = accc[0].BillingState;
        System.debug('Contact in Test Class = '+conn);
        update conn;
        bd.execute(null, accc);
        Test.stopTest();
    }

}

The above Test class Covers the 82% lines but I wanted to have 100%, can anyone please help.

Best Answer

This is because you call the execute method of your batch like a normal class.

To launch a batch you have to use the Database.executeBatch() method.

So for you test, you have to replace the line: bd.execute(null, accc); by:

Database.executeBatch(new BatchApexDemo());
Related Topic