Tag Archives: Batch Apex

Salesforce Schedulable Apex Test Class

Batch Class:

global class AccountBatch implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC){
        String query = 'SELECT Id, Name, Industry FROM Account';                
        return Database.getQueryLocator(query);     
    }
    
    global void execute(Database.BatchableContext BC, List<Account> accList){        
        for(Account acc : accList){          
            acc.Industry = 'Banking';        
        }        
        update accList;       
    }
    
    global void finish(Database.BatchableContext BC) {
        
    }
}

Schedulable Class:

global class AccountBatchScheduled implements Schedulable {
    
    global void execute(SchedulableContext sc) {
        AccountBatch objBatch = new AccountBatch(); 
        Database.executebatch(objBatch);
    }
}

Test Class:

@isTest
private class AccountBatchScheduledTest{
    
    static testmethod void schedulerTest(){
        
        String cronexpression = '0 0 0 15 3 ? *';

        Account acc = new Account();
        acc.Name = 'Test Account';
        Insert acc;
        
        Test.startTest();
        String jobId = System.schedule('ScheduleBatchApexClass',  cronexpression, new AccountBatchScheduled());
        CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE id = :jobId];
        System.assertEquals(cronexpression, ct.CronExpression);
        System.assertEquals(0, ct.TimesTriggered);
        Test.stopTest();
    }
}

Batch Apex With Webservice Callout

To make a Webservice callout in batch Apex, we have to implement Database.AllowsCallouts interface in the class definition. Here is an example to make webservice callout in batch apex.

Batch Apex:

global class AccountBatchApex implements Database.Batchable<sObject>, Database.AllowsCallouts{
    
    global Database.QueryLocator start(Database.BatchableContext bc){
        String soqlQuery = 'SELECT Name, AccountNumber, Type From Account';
        return Database.getQueryLocator(soqlQuery);
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope){
        
        for (Account acc : scope){
            if(acc.Type.equals('Customer - Direct')){
                try{
                    HttpRequest request = new HttpRequest();
                    HttpResponse response = new HttpResponse();
                    Http http = new Http();
                    
                    String username = 'YourUsername';
                    String password = 'YourPassword';
                    Blob headerValue = Blob.valueOf(username + ':' + password);
                    String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue);
                    
                    request.setHeader('Authorization', authorizationHeader);
                    request.setHeader('Content-Type', 'application/json');
                    request.setEndpoint('Your Endpoint URL');
                    request.setMethod('POST');
                    request.setBody('Information to Send');
                    response = http.send(request);
                    if (response.getStatusCode() == 200) {
                        String jsonResponse = response.getBody();
                        System.debug('Response-' + jsonResponse);
                    }
                }
                catch(Exception){
                    System.debug('Error-' + e.getMessage());   
                }
            }
        }
    }
    
    global void finish(Database.BatchableContext bc){
        
    }
}

Note: Total number of callouts (HTTP requests or Web services calls) is 100, that means if you have one callout in your execute method you can keep batch size as 100.

Salesforce Stateful Batch Apex

Batch Apex is stateless by default. That means for each execution of your execute method, you receive a fresh copy of your object. All fields of the class are initialized, static and instance. If your batch process needs information that is shared across transactions, one approach is to make the Batch Apex class itself
stateful by implementing the Database.Stateful interface. Here is an example of stateful batch apex. In below example I want to count the “Customer – Direct” account records processed by the batch class.

Batch Apex:

global class AccountBatchApex implements Database.Batchable<sObject>, Database.Stateful{
    
    global integer numberofDirectCustomers = 0;
    
    global Database.QueryLocator start(Database.BatchableContext bc){
        String soqlQuery = 'SELECT Name, AccountNumber, Type From Account';
        return Database.getQueryLocator(soqlQuery);
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope){
        
        for (Account acc : scope){
            if(acc.Type.equals('Customer - Direct')){
                numberofDirectCustomers++;
            }
        }
    }
    
    global void finish(Database.BatchableContext bc){
        
    }
}

Schedule Batch Apex For Every Hour

Batch Class:

global class accountBatch implements Database.Batchable<sobject> {
  
    global Database.QueryLocator start(Database.BatchableContext bc){
      
        String query = 'SELECT Id, Name FROM Account';
        return Database.getQueryLocator(query);
    }
      
    global void execute(Database.BatchableContext bc, List<account> scope) {
      
        for(Account a : scope) {
            a.Name = a.Name + 'Updated';
        }
        update scope;
    } 
      
    global void finish(Database.BatchableContext bc) {
      
    }
}

Scheduled Class:

global class accountBatchSchedule implements Schedulable{
	global void execute(SchedulableContext sc) {
		//invoke the batch class
        Database.executeBatch(new accountBatch());
    }
}

Execute below code from anonymous window in developer console. This will scheduled the job to run in every hour starting from 12:00 AM.

accountBatchSchedule sc = new accountBatchSchedule();
//Define cron expression
String cronExp = '0 0 * * * ?';
String jobID = System.schedule('Update Account', cronExp, sc);

Test Class for Batch Apex in Salesforce

Batch Class:

global class BatchAccount implements Database.Batchable<sObject> 
{
    global Database.QueryLocator start(Database.BatchableContext BC) {
		
        return Database.getQueryLocator('SELECT Id,Name FROM Account');
    }
	
    global void execute(Database.BatchableContext BC, List<Account> scope) {
		
        for(Account a : scope)
        {
            a.Name = a.Name + ' Updated';
        }
        update scope;
    }
	
    global void finish(Database.BatchableContext BC) {
		
    }
}

Test Class:

@isTest 
public class BatchAccountTest 
{
    static testMethod void test() 
    {
        List<Account> accList = new List<Account>();
        for(Integer i = 0 ; i < 200; i++)
        {
            Account acc = new Account();
            acc.Name = 'Name' + i;
            accList.add(acc);
        }
        Insert accList;
        
		Test.startTest();
		BatchAccount obj = new BatchAccount();
		DataBase.executeBatch(obj); 
		Test.stopTest();
		
		//Verify accounts updated
		List<Account> accUpdatedList = [SELECT Id, Name FROM Account];
		System.assert(accUpdatedList[0].Name.Contains('Updated'));
    }
}