1

I have an apex class which fetches and upserts data from external source to Salesforce.

Below is the batch class:

global class PolicyCalloutBatchClass implements Database.Batchable<Integer>,Database.AllowsCallouts, Database.Stateful {
 global Iterable<Integer> start(Database.BatchableContext context) {
       Integer[] values = new Integer[0];
while(values.size() < 2999) {
    values.add(values.size());
}
return Test.isRunningTest() ? new Integer[1] : values ;
}
    global void execute(Database.BatchableContext context, Integer[] values) {
        
        HttpRequest policyreq = new HttpRequest();
        policyreq.setMethod('GET');
        policyreq.setTimeout(120000);
        policyreq.setEndpoint('<endpoint>');
        policyreq.setHeader('Authorization', 'Bearer ' + <token>);
        Http policyhttp = new Http();
        HTTPResponse policyres = policyhttp.send(policyreq);
        String policyresponse = policyres.getBody();
        JsonParser objJsonParser = (JsonParser) JSON.deserialize(policyresponse, JsonParser.class);  
        
        JsonParser.cls_value clsValue = objJsonParser.value;
        Map<String, JsonParser.cls_data> clsDataMap = new Map<String, JsonParser.cls_data>();
        for(JsonParser.cls_data objClsData: clsValue.data){
            clsDataMap.put(objClsData.id, objClsData);
        }
        list<Policy__c> updatelist = new list<Policy__c>();
        for (String eachIdFromMap : clsDataMap.keySet()){
            
            Policy__c policy = new Policy__c(
                unique_id__c = clsDataMap.get(eachIdFromMap).id,
                agent_id__c = clsDataMap.get(eachIdFromMap).agentId);
            updatelist.add(policy);  
        }
        try{
            upsert updatelist unique_id__c;    
        }
        catch(DmlException e){
            system.debug('This class didnt compile');
        }
    }
    global void finish(Database.BatchableContext context) {
        
    }
}

Below is my Mock test class:

global class MockHttpResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        String jsonbody = '{ ' +
              '"id": "11111"' +
              '}' ; 
        HttpResponse objHttpResponse = new HttpResponse();
        objHttpResponse.setBody(jsonbody);
        objHttpResponse.setHeader('Content-Type', 'application/json');
        objHttpResponse.setStatusCode(200);
        return objHttpResponse;
    }
}

Below is my test class:

  @isTest 
private class PolicyUpdateController_Test {
    static testMethod void testPostCallout() {
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());  
        
        Test.startTest();
        PolicyCalloutBatchClass  obj = new PolicyCalloutBatchClass ();
        Database.executeBatch(obj, 50); 
        Test.stopTest();
        
    }
}

Though I am not seeing any errors in my code, my batch apex class is covered only 8%. Complete execute method is left uncovered.

Can anyone please suggest the changes to my above test class so that I can get this done.

Thank you in advance!

8
  • 5
    Does this answer your question? Test run for Web Service Callout batch class – Nagendra Singh Nov 30 '20 at 13:46
  • Isn't this the same question you asked yesterday salesforce.stackexchange.com/questions/327558/… – Nagendra Singh Nov 30 '20 at 13:48
  • Earlier the issue was due to test class running in Infinite loop which was resolved. But even though I have updated the test class as per API documentation, I could see that the class is covered only 8%. That's the reason why I came here for suggestion! – SFDCUser Nov 30 '20 at 14:06
  • I still see this line while(values.size() < 2999 || Test.isRunningTest()) values.add(values.size()); which is incorrect. please check the solution in the above link. – Nagendra Singh Nov 30 '20 at 14:08
  • 1
    I made a mistake in my previous post. Correct in both plates now. – Nagendra Singh Nov 30 '20 at 15:11
2

Change you start to this and it should work as it has to add values in array before passing that to execute method. So here if test is running we clear the array and add 1 so that the execute gets called at least once.

global Iterable<Integer> start(Database.BatchableContext context) {
    Integer[] values = new Integer[0];
    while(values.size() < 2999) {
        values.add(values.size());
    }
    if(Test.isRunningTest()) {
        values.clear();
        values.add(1);
    }

    return values ;
}
3
  • Thanks @NarendraSingh. I need one small suggestion pls...I am getting null pointer exception in the line policyreq.setHeader('Authorization', 'Bearer ' + <token>). In real time scenario, this line is working and I could able to see the response successfully where as in test class, it is failing. Could you please suggest any changes here? – SFDCUser Dec 1 '20 at 7:31
  • 1
    For token you can do something like this: String token = //Get your token from anywhere and assign it to token variable. Then do : token = Test.isRunningTest() ? '' : token; So that your you can assign any dummy variable to token parameter. Or If you fetching the token from DB, just create the same record on Test class to fetch the token from DB. – Nagendra Singh Dec 1 '20 at 8:02
  • Thanks @Narendra. – SFDCUser Dec 1 '20 at 8:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.