[SalesForce] Test Class for Batch that sends callout

I'm unable to cover an execute method of a batch class. Do I need to use a mock class for response?

It's my first time testing a batch class with a callout. Following is the method…

global void execute(Database.BatchableContext BC, List<sObject> scope){
   try{
   List<Obhect__c> LUB = (List<Obhect__c>)scope;
   String Skey   = 'test';


   if(LUB.size()>0){
    for(Obhect__c UB : LUB){
       String address = Class_Name.getAdd(UB);
       HttpResponse resp1 = Class_Name.CallMe('callout:GoogleMapsLocation/geocode/json?test1='+test1+'&test2='+test2);

        if(resp1!=null){
       Addr.Location location = Class_Name.getLatLng(resp1);
       lat = Class_Name.getLa(loc);
       lng = Class_Name.getLn(loc);
        }     
       String timeStamp= String.valueOf(((DateTime.now().getTime())/1000));
       HttpResponse response2 = Class_Name.CallMe('callout:GoogleMapsLocation/timezone/json?location='+String.valueOf(lat)+','+String.valueOf(lng)+'&timestamp='+timeStamp+'&key='+key);
        if(response2!=null){ 
       Class_TimeZoneResponse timeZoneResp = Class_Name.getTimeZoneDetails(response2);

       Integer offsetTotal      = timeZoneResp.dstOffset+timeZoneResp.rawOffset;
       String Timezone          = timeZoneResp.timeZoneName;
       UB.Offset__c   = String.valueof(offsetTotal);
       UB.Recalulate_Odd__c = false;
       UB.TimeZone__c = Timezone;
        }
   }
   Database.update(LUB,false);
   }      
}

Following is what I tried…(Forgive me I've made too many changes to post it publicly)

    List<Obhect__c> BUList1 = [SELECT City__c,place_c FROM Obhect__c limit 1];

        Database.QueryLocator QL;
        Database.BatchableContext BC;       

        Test.StartTest();

        mainclassbatch msb = new mainclassbatch ();    
        QL = msb.start(BC);      


        Class_Name.getAdd(BUList1[0]);

        Class_LatitudeLogitudeResponse llr = new Class_LatitudeLogitudeResponse ();

       try{
       Database.update(BUList1,false);
       }
       Catch(Exception e) {}

        msb.execute(BC,BUList1);
        msb.finish(BC);

I would really appreciate if someone can point me in the right direction. Thanks

===EDIT===

This is a mock class…

@isTest
global class mainclassmock implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {

        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"a":"k"}');
        res.setStatusCode(200);
        return res;
    }
}

I added a mock class as with a fake body …

mainclassmock mock = new mainclassmock ();

Test.setMock(HttpCalloutMock.class, mock);
mbc.finish(null);

What am I missing? Code coverage remains same.

Best Answer

You have several issues with your test class. First, yes you do need Mock responses for each of the two callouts your batch class makes. See Testing HTTP Callouts Using MultiStaticResourceCalloutMock.

Next, your following code is not the way to call and test your batch class:

   try{
   Database.update(BUList1,false);
   }
   Catch(Exception e) {}

    msb.execute(BC,BUList1);
    msb.finish(BC);

There's no need for a try-catch block when you call a batch class. You also should simply call the class, not it's methods by doing something like this (example assumes mainclassbatch is the name of your batch class since you've not included all of your code):

Test.Start.Test();
mainclassbatch msb = new mainclassbatch (); 
msb.query = [SELECT City__c,place_c FROM Obhect__c limit 1];
ID batchprocessid = Database.executeBatch(msb);
Test.Stop.Test();

// now make your assertions that the class ran and produced the expected results.

See Testing Batch Apex towards the bottom of the page in the Apex Developer Guide for a full example.

Related Topic