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){
        
    }
}

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'));
    }
}

Undelete Records in Salesforce Using Batch Apex

Sample Code:

global class AccountUndeleteBatchApex implements Database.Batchable<sObject>{
    
    global Database.queryLocator start(Database.BatchableContext bc){
        String query = 'SELECT Id, Name FROM Account WHERE IsDeleted = True ALL ROWS';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope){
        List<Account> accList = new List<Account>();
        for(Account s:scope){
            //Write your logic
            accList.add(s);
        }
        Undelete accList;
    }
    
    global void finish(Database.BatchableContext bc){
        
    }
}