+ Start a Discussion
gazzer82gazzer82 

Unit Test, Callout No Response with Static Resource

Bit stuck on another one i'm afraid, i am trying to write a unit test for a bulk APEX class.

 

The class has a calllout to the google api, so i have created a static resource which i am feeding in via a mock, so i can complete testing of processing the JSON that is returned. However for some reason the response is always empty.

 

Now the very odd thing is that if i use exactly the same callout/JSON code, and the same mock code on a previous @future call, then it does return fine.

 

Here is the class:

 

global class mileage_bulk implements Database.Batchable<sObject>,

  Database.AllowsCallouts

{

global Database.QueryLocator start(Database.BatchableContext BC)

{

String query = 'SELECT Id,Name,Amount,R2_Job_Ref__c,R2_Shipping_Post_Code__c,Shipping_Postcode_2__c FROM Opportunity WHERE R2_Shipping_Post_Code__c != null';

return Database.getQueryLocator(query);

//system.debug('Executing'+query);

}

 

global void execute(Database.BatchableContext BC, List<Opportunity> scope)

{

system.debug(scope);

for(Opportunity a : scope)

{

 

        String startPostcode = null;

        startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');

        String endPostcode = null;

        String endPostcodeEncoded = null;

        if (a.R2_Shipping_Post_Code__c != null){

        endPostcode =   a.R2_Shipping_Post_Code__c;

        Pattern nonWordChar = Pattern.compile('[^\\w]');

endPostcode = nonWordChar.matcher(endPostcode).replaceAll('');

        endPostcodeEncoded =   EncodingUtil.urlEncode(endPostcode, 'UTF-8');

            }   

        Double totalDistanceMeter = null;

        Integer totalDistanceMile = null;

       String responseBody = null;

       Boolean firstRecord = false;

        

        String ukPrefix = 'UKH';

        if (a.R2_Job_Ref__c != null){    

        if ((a.R2_Job_Ref__c).toLowerCase().contains(ukPrefix.toLowerCase())){

        system.debug('Is Hemel Job');

        startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');

        } else {

        system.debug('Is Bromsgrove Job');

        startPostcode = EncodingUtil.urlEncode('B604AD', 'UTF-8');

        }

        }

        

        // build callout

        Http h = new Http();

        HttpRequest req = new HttpRequest();

        req.setEndpoint('http://maps.googleapis.com/maps/api/directions/json?origin='+startPostcode+'&destination='+endPostcodeEncoded+'&units=imperial&sensor=false');

        req.setMethod('GET');

        req.setTimeout(60000);

        system.debug('request follows');

        system.debug(req);

 

try{  

            // callout

            HttpResponse res = h.send(req);

            

            // parse coordinates from response

            

            JSONParser parser = JSON.createParser(res.getBody());

            

            responseBody = res.getBody();

            system.debug(responseBody);

            

            while (parser.nextToken() != null) {

                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && 

                    (parser.getText() == 'distance')){

                       parser.nextToken(); // object start

                       while (parser.nextToken() != JSONToken.END_OBJECT){

                           String txt = parser.getText();

                           parser.nextToken();

                           //system.debug(parser.nextToken());

                           //system.debug(txt);

                           if (firstRecord == false){

                           //if (txt == 'text'){

                               //totalDistanceMile = parser.getText();

                               system.debug(parser.getText());

                           //}

                           if (txt == 'value'){

                               totalDistanceMeter = parser.getDoubleValue();

                               double inches = totalDistanceMeter*39.3701;

                               totalDistanceMile = (integer)inches/63360;

                               system.debug(parser.getText());

                               firstRecord = true;

                           }

                           }

                       }

                    

                }

            }

  

           

        } catch (Exception e) {

        }

 

//system.debug(accountId);

        system.debug(a);

        system.debug(endPostcodeEncoded);

        system.debug(totalDistanceMeter);

        system.debug(totalDistanceMile);

           

            // update coordinates if we get back 

            if (totalDistanceMile != null){

            system.debug('Entering Function to Update Object');

                a.DistanceM__c = totalDistanceMile;

                a.Shipping_Postcode_2__c = a.R2_Shipping_Post_Code__c;

                //update a;        

            }  

}

update scope;

}

 

 

global void finish(Database.BatchableContext BC)

{

}

}

 

and here is the test class;

 

/**

 * This class contains unit tests for validating the behavior of Apex classes

 * and triggers.

 *

 * Unit tests are class methods that verify whether a particular piece

 * of code is working properly. Unit test methods take no arguments,

 * commit no data to the database, and are flagged with the testMethod

 * keyword in the method definition.

 *

 * All test methods in an organization are executed whenever Apex code is deployed

 * to a production organization to confirm correctness, ensure code

 * coverage, and prevent regressions. All Apex classes are

 * required to have at least 75% code coverage in order to be deployed

 * to a production organization. In addition, all triggers must have some code coverage.

 * 

 * The @isTest class annotation indicates this class only contains test

 * methods. Classes defined with the @isTest annotation do not count against

 * the organization size limit for all Apex scripts.

 *

 * See the Apex Language Reference for more information about Testing and Code Coverage.

 */

@isTest

private class mileage_bulk_tests{

 

    static testMethod void myUnitTest() {

         Opportunity opp1 = new Opportunity(name = 'Google Test Opportunity',R2_Job_Ref__c = 'UKH12345',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());

 insert opp1;

 Opportunity opp2 = new Opportunity(name = 'Google Test Opportunity 2',StageName = 'qualified',CloseDate = Date.today());

 insert opp2;

 Opportunity opp3 = new Opportunity(name = 'Google Test Opportunity 3',R2_Job_Ref__c = 'UKB56789',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());

insert opp3;

 

 

StaticResourceCalloutMock mock = new StaticResourceCalloutMock();

mock.setStaticResource('googleMapsJSON');

mock.setStatusCode(200); // Or other appropriate HTTP status code

mock.setHeader('Content-Type', 'application/json'); // Or other appropriate MIME type like application/xml

 

//Set the mock callout mode

Test.setMock(HttpCalloutMock.class, mock);

 

system.debug(opp1);

system.debug(opp1.id);

 

//Call the method that performs the callout

Test.startTest();

mileage_bulk b = new mileage_bulk();

database.executeBatch((b), 10);

Test.stopTest();

    }

}

 

Help greatly appreciated!

 

Thanks

 

Gareth

 

gazzer82gazzer82

Also, if i run this class manually by triggering it from force IDE it runs as expected.

 

Cheers

 

Gareth