function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
sandy ksandy k 

How to write test coverage for batch class

Hi Guys,
Here is the batch class, how to write test coverage for batch class

public class ServiceBatchable implements Database.Batchable<sObject>, Database.Stateful {
    private Id lastJobId = null;
    private Id serRecTypeId = null;
    public ServiceBatchable () {
    }
  public Database.QueryLoSeror start(Database.BatchableContext BC) {
        Integer limitInt = 10000;
        List<AsyncApexJob> aajList = new List<AsyncApexJob>();
                                if(lastJobId!=null && lastJobId!=BC.getJobId()) {
             aajList.addAll([SELECT Id, Status, CompletedDate FROM AsyncApexJob WHERE ID =: lastJobId and JobType!='BatchApexWorker' and Status not in ('Aborted','Completed','Failed')]);
        }
                                if(lastJobId==null || aajList.isEmpty()) {
            lastJobId = BC.getJobId();
            if(serRecTypeId ==null) {
                RecordType rt = opportunityRTMap.get('Service Record');
                if(rt!=null) {
                   serRecTypeId = rt.Id;
                }
            }
        }
        if(lastJobId!=BC.getJobId()) {
            limitInt = 0;
            System.debug('ServiceBatchable: Previous Job alive still - aborting '+BC.getJobId());
        }
return Database.getQueryLocator([
            select id,CurrencyIsoCode,StageName,Ser_Currency_Code__c,Ser_Line_Item_ID__c,Ser_Duration__c,Ser_Start_Date__c,Ser_Monthly_Amount__c,SER_Updated__c
            from Opportunity where
             ((StageName='1 - Lead' and Ser_Line_Item_ID__c != null) or (StageName!='1 - Lead')) and
             SER_Updated__c = true and
             External_Id__c != null and
             RecordTypeId=: serRecTypeId and
             isDeleted=FALSE
             limit :limitInt
            ]);
    }
 public void execute(Database.BatchableContext BC, List<Opportunity> scope){
        Map<Id,OpportunityLineItem> opportunityLineItemMap = new Map<Id,OpportunityLineItem>();
        for(OpportunityLineItem oli : [select id,OpportunityId,X2022_Revenue__c,X2023_Revenue__c,Wave__c,UnitPrice,ServiceDate,Seats__c,Quantity,PricebookEntryId,Language__c,FTE__c,Delivery_LoSerion__c from OpportunityLineItem where OpportunityId in :scope]) {
            opportunityLineItemMap.put(oli.Id,oli);
        }
        List<OpportunityLineItem> removeOpportunityLineItemList = new List<OpportunityLineItem>();
        List<Opportunity> newScope = new List<Opportunity>();
        List<Opportunity> alteredScope = new List<Opportunity>();
        for(Opportunity o: scope) {
            if(o.StageName=='1 - Lead' && opportunityLineItemMap.containsKey(o.Ser_Line_Item_ID__c)) {
                removeOpportunityLineItemList.add(opportunityLineItemMap.remove(o.Ser_Line_Item_ID__c));
                o.Ser_Line_Item_ID__c = null;
                o.CurrencyIsoCode=o.Ser_Currency_Code__c;
                alteredScope.add(o);
            } else if(o.StageName!='1 - Lead' && o.CurrencyIsoCode!=o.Ser_Currency_Code__c) {
                if(opportunityLineItemMap.containsKey(o.Ser_Line_Item_ID__c)) {
                              removeOpportunityLineItemList.add(opportunityLineItemMap.remove(o.Ser_Line_Item_ID__c));
                                o.Ser_Line_Item_ID__c = null;
               }
                o.CurrencyIsoCode=o.Ser_Currency_Code__c;
                alteredScope.add(o);
                newScope.add(o);
            } else if(o.StageName!='1 - Lead' && opportunityLineItemMap.containsKey(o.Ser_Line_Item_ID__c)){
                newScope.add(o);
            } else if(o.StageName!='1 - Lead' && !opportunityLineItemMap.containsKey(o.Ser_Line_Item_ID__c)){
                o.CurrencyIsoCode=o.Ser_Currency_Code__c;
                newScope.add(o);
            }
        }
        // Delete those marked as invalid
        delete removeOpportunityLineItemList;
        // Remove old reference after we delete
        update alteredScope;
       
        // Opportunity map.
                                Map<Id,Opportunity> ServiceOpportunityMap = new Map<Id,Opportunity>(newScope);
        List<OpportunityLineItem> upsertOpportunityLineItemID = new List<OpportunityLineItem>();

        // Populate ServicePriceBookEntryMap with map of ISO code to ID
                                Map<String,PricebookEntry> ServicePriceBookEntryMap = new Map<String,PricebookEntry>();
        for(PricebookEntry pbe : [select id, CurrencyisoCode from PricebookEntry where ProductCode = 'Ser']) {
            if(!ServicePriceBookEntryMap.containsKey(pbe.CurrencyIsoCode)) {
               ServicePriceBookEntryMap.put(pbe.CurrencyisoCode,pbe);
            }
        }
for(Opportunity o: newScope) {
            Id pricebookEntryId = null;
            if(ServicePriceBookEntryMap.containsKey(o.Ser_Currency_Code__c)) {
                pricebookEntryId = ServicePriceBookEntryMap.get(o.Ser_Currency_Code__c).Id;
            }
            OpportunityLineItem oli;
            // get old lineitem
            if(opportunityLineItemMap.containsKey(o.Ser_Line_Item_ID__c)) {
                oli = opportunityLineItemMap.get(o.Ser_Line_Item_ID__c);
            }
            // if none found create new one and setup defaults
            if(oli==null) {
                oli = new OpportunityLineItem();
                oli.OpportunityId = o.Id;
                oli.PricebookEntryId = pricebookEntryId;
                oli.Seats__c = 0;
                oli.Wave__c = '1';
                oli.X2023_Revenue__c = 0;
                oli.X2022_Revenue__c = 0;
                oli.Delivery_LoSerion__c = 'Other';
                oli.FTE__c = 0;
                oli.Language__c = 'English';
            }
            // New or Update copy these fields
            oli.Quantity = Math.max(1,o.Ser_Duration__c);
            oli.ServiceDate = o.Ser_Start_Date__c;
            oli.UnitPrice = o.Ser_Monthly_Amount__c;
            upsertOpportunityLineItemID.add(oli);
        }
       if(!upsertOpportunityLineItemID.isEmpty()) {
            upsert upsertOpportunityLineItemID;
            for(OpportunityLineItem oli : upsertOpportunityLineItemID) {
                Opportunity o = ServiceOpportunityMap.get(oli.OpportunityId);
                o.Ser_Line_Item_ID__c = oli.Id;
                o.SER_Updated__c = false;
            }
            update newScope;
        }
    }
public void finish(Database.BatchableContext BC){       
        if(BC.getJobId()==lastJobId) {
            lastJobId=null;
        }
                }   
private Map<String,RecordType> opportunityRTMap = getRecordTypeMap('Opportunity');
private List<RecordType> getRecordTypes(String[] objects) {
        return [SELECT Id, name, SObjectType FROM RecordType WHERE SObjectType in :objects order by SobjectType, Name];
    }
private Map<String,RecordType> getRecordTypeMap(String objectName) {
        Map<String,RecordType> target = new Map<String,RecordType>();
        for(RecordType r : getRecordTypes(new String[] {objectName})) {
            target.put(r.name,r);
        }
        return target;
    }
   private Map<String,RecordType> getRecordTypeMap(String[] objects) {
        Map<String,RecordType> target = new Map<String,RecordType>();
        for(RecordType r : getRecordTypes(objects)) {
            target.put(r.SObjectType+'.'+r.name,r);
        }
        return target;
    }
     public static ID execute() {
        try {
            return System.scheduleBatch(new ServiceBatchable(),'ServiceBatchable',1,200);
        } Catch (Exception ex) {
            // We don't care that another is setup
            System.debug(ex);
        }
        return null;
    }
}

 
AnkaiahAnkaiah (Salesforce Developers) 
Hi Sandy,

Refer the below links will help you to proceed further on your test class.
https://jayakrishnasfdc.wordpress.com/2021/01/02/apex-test-class-for-batch-apex/
https://acesalesforce.com/test-class-batch-class/

Thanks!!
CharuDuttCharuDutt
Hii Sandy
Try Below Code
@isTest
public class ServiceBatchableTest {
    @isTest
    public Static void unitTest(){
        Id serviceRecordTypeId = Schema.SObjectType.Opportunity.getRecordTypeInfosByName().get('Service Record').getRecordTypeId();
        Account Acc = new Account();
        Acc.Name = 'Test';
        insert Acc;
        
        Opportunity oOpp = new Opportunity();
        oOpp.Name = 'Test Opp';
        oOpp.CurrencyIsoCode = 'USD';
        oOpp.CloseDate = System.today();
        oOpp.StageName = '1 - Lead';
        oOpp.AccountId = Acc.Id;
        oOpp.RecordTypeId = serviceRecordTypeId;
        oOpp.Ser_Currency_Code__c = 'USD';
        oOpp.Ser_Line_Item_ID__c = //Fill This;
        oOpp.Ser_Duration__c = 5;
        oOpp.Ser_Start_Date__c = system.today();
        oOpp.Ser_Monthly_Amount__c = 7000;
        oOpp.SER_Updated__c = true;
        oOpp.External_Id__c = //Fill This;
        insert oOpp;
        
        Product2 p = new Product2();
        p.Name = ' Test Product ';
        p.Description='Test Product Entry For Product';
        p.productCode = 'Ser';
        p.isActive = true;
        insert p;
        
        PricebookEntry standardPrice = new PricebookEntry();
        standardPrice.Pricebook2Id = Test.getStandardPricebookId();
        standardPrice.Product2Id = p.Id;
        standardPrice.UnitPrice = 100;
        standardPrice.IsActive = true;
        standardPrice.UseStandardPrice = false;
        standardPrice.CurrencyisoCode ='USD';
        insert standardPrice ;
        
        OpportunityLineItem oppLineItem = new OpportunityLineItem();
        oppLineItem.OpportunityId = oOpp.Id;
        oppLineItem.PricebookEntryId = standardPrice.Id;
        oppLineItem.UnitPrice = 7000;
        oppLineItem.Quantity = 5;
        oppLineItem.X2022_Revenue__c = 0;
        oppLineItem.X2023_Revenue__c = 0;
        oppLineItem.Wave__c = '1;
        oppLineItem.ServiceDate = system.today();
        oppLineItem.Seats__c = 0;
        oppLineItem.Language__c = 'English';
        oppLineItem.FTE__c = 0;
        oppLineItem.Delivery_LoSerion__c = 'Other';
        insert oppLineItem;
        
        ServiceBatchable lp = new ServiceBatchable();
        Id batchId = Database.executeBatch(lp);
        
    }
}
Please Mark It As Best Answer If It Helps
Thank You!
sandy ksandy k
Hi Charu Thanks! for your response,

below is the error while executing test methos

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, You may not Change an opportunity owned by the Salesforce system..: []
 
sandy ksandy k
Finally after fixing all of them I am getting below error
System.LimitException: Too many SOQL queries: 101