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
sfdc007sfdc007 

Test class for Batch class help needed urgent

Hi,

I am trying to write test class for the below batch class ,

I am getting the following error on my test class


System.NullPointerException: Business Hours Id cannot be null 
 
MY BATCH CLASS :




global class CROBatchController implements Database.Batchable<sObject> {
    global string strBusHrId;
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        BusinessHours bh = [SELECT Id, Name FROM BusinessHours WHERE Name = 'Defend'];
        if(bh != null){
            strBusHrId = bh.Id; 
        }
        // SOQL Query to fetch the values of hours , minutes and days
        String query = 'select Id, Status__c,CreatedDate From Team_Form__c where Status__c = \'New\' and Engagement_Team__r.Initial__c = \'Defend\'';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Team_Form__c> lstTF)
    {
        system.debug('strBusHrId=>'+strBusHrId);
        List<Id> lstTFIds = new List<Id>();
        map<Id,DateTime>tfCDtMap = new map<Id,DateTime>();
        
        for(Team_Form__c objTF: lstTF){
        	lstTFIds.add(objTF.Id); 
        }
        
        for(Team_Form__History objTFHis:[select Id, CreatedDate, NewValue,OldValue,ParentId from Team_Form__History where Field = 'Status__c' and ParentId in :lstTFIds Order By CreatedDate ASC]){
            if(string.valueof(objTFHis.NewValue) == 'New'){
            	tfCDtMap.put(objTFHis.ParentId,objTFHis.CreatedDate);
            }
        }
        
        Datetime startDate, endDate;
        endDate = System.Datetime.now();        
        string subject;
        map <Id, String> chatterTextMap = new map <Id, String> ();
        map <Id, set <Id>> mentionIdMap = new map <Id, set <Id>> ();
        List<Id> lsmentionId = new List<Id>();        
        for(Team_Group_Member__c objTGM :[select Id, Engagement_Team__r.Initial__c,User__c From Team_Group_Member__c where User_Role__c = 'Super User' and Engagement_Team__r.Initial__c = 'Defend']){                
            lsmentionId.add(objTGM.User__c);
        }        
        for(Team_Form__c objTF: lstTF)
        {            
            if(tfCDtMap.get(objTF.Id) != null){
                startDate = tfCDtMap.get(objTF.Id);
            }else{
               startDate = objTF.Createddate; 
            }
			long businessMillisecondsDiff = BusinessHours.diff(strBusHrId, startDate, endDate);             
            long millitoHrs = businessMillisecondsDiff/3600000;
            if(millitoHrs >= 48){                
                subject = 'TF is in \'New\' status for more than 48hrs';
                chatterTextMap.put(objTF.Id,Subject);
                mentionIdMap.put(objTF.Id,new set <Id>(lsmentionId));
                if(chatterTextMap.size()>0){
                    CommunityUtility.postCustomFeedItem (mentionIdMap, chatterTextMap, 'AllUsers');
                }
            }
        }         
    }  
    global void finish(Database.BatchableContext BC)
    {
    }
}
MY TEST CLASS

@isTest
Public class CROBatchController_Test{
public static testMethod void testBatch() {
 skipingHelper.SkippThemAll();
 BusinessHours bh = [SELECT Id, Name FROM BusinessHours WHERE Name = 'Defend'];
 Account acct = GPSTestUtilities.createTestAccount();
 Opportunity oppty1 = GPSTestUtilities.createTestOpportunity(acct.Id);
 Engagement_Script__c ES = GPSTestUtilities.createEngagementScript(acct.Id,oppty1.Id);  
 Engagement_Team__c ET = createEngagementTeamDefend();   
 Team_Form__c TF = createTeamFormDefend(ES.Id);  
 //Team_Group_Member__c  TFMem =createTeamGroupMemberDefend(); 
    
    Test.startTest();
	   CROBatchController mbcCon=new CROBatchController();
       //mbcCon.businessHrsId = bh.Id;
		ID batchprocessid = Database.executeBatch(mbcCon);
	Test.stopTest();
}
    	 public static Engagement_Team__c createEngagementTeamDefend() {  
        list<Engagement_Team__c> ET1 =[SELECT ID,Initial__c FROM Engagement_Team__c WHERE  Initial__c ='Defend' limit 1];
        Engagement_Team__c tmobj = new Engagement_Team__c();
        if(ET1.size()==0){
            Engagement_Team__c ET = new Engagement_Team__c();
            ET.Engagement_Model__c = 'Queue';
            ET.IsActive__c = true;
            ET.Engage_Direct__c = true;
            ET.Engage_Period__c =  'PreSales';
            ET.Engaged_By__c = 'Sales & Support';
            ET.Group_API_Name__c='EP_Defend_Group';
            ET.Queue_API_Name__c ='EP_Defend_Queue';
            ET.Super_User_Group__c='EP_Defend_SuperUser';
            ET.Initial__c ='Defend';
            ET.Team_Name__c ='Defend Team';           
            insert ET;
            tmobj =  ET;               
        }
        else{
            tmobj= ET1[0];}        
        return tmobj;
    }
    
    public static Team_Form__c createTeamFormDefend(Id ESId) {
        Engagement_Team__c ET=createEngagementTeamDefend();
        
        Engaged_Team__c engtm= new Engaged_Team__c (Engagement_Team__c=ET.Id,Engagement_Script__c=ESId);
        Insert engtm;
        
        Id rectypeid=[select Id,name from RecordType where NAME='Defend' and SobjectType='Team_Form__c' limit 1].Id;
        Team_Form__c TF = new Team_Form__c();
        TF.Engagement_Script__c = ESId;
        TF.Engagement_Team__c = ET.Id;    
        TF.Status__c='New';
        TF.RecordTypeId = rectypeid; 
        TF.OwnerId =  UserInfo.getUserId();
        TF.Revision_Reason__c = 'Cost/Price Impacting Change in Requirements';
        TF.Revision_Reason_Detail__c = 'Number of sites';
        TF.IsActive__c = true;
        insert TF;
        
        return TF;
    }

    
}


Kindly help me what is the issue here pls

Thanks in Advance
James LoghryJames Loghry
The root cause of your error looks to be happening in the execute method of your batch class, when you try to calculate the business hours difference with the BusinessHours.diff() call, and happen to pass in a null Id field.

BusinessHours *should* be available in unit tests, without need for creating them in your unit test.  At least the default business hours should.  I would first check that the following SOQL query returns a BusinessHour record by using System.debug in your unit test: 
 
[SELECT Id, Name FROM BusinessHours WHERE Name = 'Defend']

Additionally, it may be that your strBusHrId variable in your execute method is losing context in your batch class.  What does the following line output in your execute method (line 21 in your example)?
 
system.debug('strBusHrId=>'+strBusHrId);

If it's null, I would try updating your batch class to implement Database.stateful interface, OR using the private String final modifier as well per the following document: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm to see if you can get your strBusHrId variable to "stick" with the BusinessHours Id field.

Hope that helps.