0

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 || Test.isRunningTest()) values.add(values.size());
        return 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:

@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
          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();
        
      
        return policyres;
    }
}

Below is my test class:

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

Now, when I run the above test class, either the test class runs forever without any output or I could see the error as

System.LimitException: Too many callouts: 101

Can anyone please let me know if there is any way to get this done?

Thanks!

1
  • using Test.isRunningTest in code is not best practice and can be avoided by injecting the max array size via a constructor argument.
    – cropredy
    Commented Nov 29, 2020 at 17:48

2 Answers 2

2

The issue is this condition:

    while(values.size() < 2999 || Test.isRunningTest()) {
        values.add(values.size());
    }

As you have given Test.isRunningTest() or values.size() < 2999 which is true, so it goes in infinite loop. and runs forever.

It should be:

Integer[] values = new Integer[0];
while(values.size() < 2999) {
    values.add(values.size());
}
if(Test.isRunningTest()) {
    values.clear();
    values.add(1);
}

Also your mock class is incorrect:

It should be :

global class MockHttpResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        HttpResponse objHttpResponse = new HttpResponse();
        objHttpResponse.setBody('Ho');
        objHttpResponse.setStatusCode(200);
        return objHttpResponse;
    }
}

set the desired response and status code. Also not sure what are you doing with the values as I dont see any iteration happening, or do you just wanted the execute method to run multiple times.

1

The start() method runs into an infinite loop. The start() should return all records that need to be processed in the job. If your intention is to run 50 records a batch and cap it at 2999 (i.e. less than 60 batches), you could simply do:

return new Integer[2999];

Your HTTP mock class should simply focus on crafting the response body, not firing another HTTP callout.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .