3

I have batch class that makes a HTTP callout to a remote web service. To deploy into production, I have created a test class with StaticResourceCalloutMock.

I am executing the test class in a full copy sandbox and it is working fine. But when I deploy, it is failing. Not sure what is going on.

Getting the following error message

System.NullPointerException: Attempt to de-reference a null object Stack Trace: Class.InsideviewPostJob.IVPostRequest: line 26, column 1 Class.AccountAPIToInsideviewRequest.Execute: line 37, column 1

Deployment is failing at the following line in the class - InsideviewPostJob

if (res.getStatus()=='OK' && res.getstatuscode()==200) {

Test Class:

        test.startTest();
         StaticResourceCalloutMock Mock = new StaticResourceCalloutMock();
         mock.setStaticResource('AccountPostJobResp');
         mock.setstatusCode(200);
         mock.setStatus('OK');
         mock.setHeader('Accept', 'application/json');
         mock.setHeader('Content-Type', 'text/plain');
         test.setMock(HttpCalloutMock.class, Mock);
         AccountAPIToInsideviewRequest  ivapi = new  AccountAPIToInsideviewRequest();
         Database.executeBatch(ivapi, 1);

         /* ivTokenUtil test class execution*/  
         test.stopTest();    

Batch Class:

Global void Execute(Database.BatchableContext BC, List<sObject> scope)
{

    system.debug('Hello Execute');

    String CompanyIDs = '';

    List<String> ProcessedCIs = new List<String>();

    for (Sobject s : Scope)
    {        
     Account Act = (Account)s;
   /*  system.debug('Hello Execute and account:' + Act.NAME);*/

     CompanyIds += Act.Insideview_ID__c + ',' ;
     ProcessedCIs.add(Act.Insideview_ID__c);

    } 

    CompanyIds = CompanyIds.substring(0, CompanyIds.length() -1);          
    String EndpointURL = 'https://api.insideview.com/api/v1/company/job';
    string ivjobid = InsideviewPostJob.IVPostRequest(EndpointURL, CompanyIds);

Webservice Callout Class

Global class InsideviewPostJob{

    public static string IVPostRequest(String EndpointURL, String InsideViewIds) {
        String InsideviewJobId;
        System.debug('InsideViewIds: '+ InsideViewIds);
        if (InsideViewIds==null || InsideViewIds=='') {
            System.debug('No CompanyIds to send to Insideview API');
            return InsideviewJobId;
        }
        HttpRequest req = new HttpRequest();
        req.setEndpoint(EndpointURL);
        req.setMethod('POST');
        req.setHeader('accessToken', IVTokenUtils.getToken());
        req.setHeader('Accept', 'application/json');
        req.setheader('Content-Type', 'text/plain');
        req.setBody(InsideViewIds);
        system.debug('req.getBody():' + req.getBody());
        Http http = new Http();
        HttpResponse res = null;
        try {
            res = http.send(req);
        } catch(System.CalloutException e) {
            System.debug('Callout error: '+ e);
        }
        system.debug('PostJob-Resp: ' + res);
        if (res.getStatus()=='OK' && res.getstatuscode()==200) {
            String jsonData = res.getBody();
            System.debug('Post Response: '+ jsonData);
            InsideViewPostResp postResp = (InsideViewPostResp)JSON.deserialize(jsonData, InsideViewPostResp.class);

            if (postResp.jobId!=null) {
                InsideviewJobId = postResp.jobId;
            }
            return InsideviewJobId;
        }
       return InsideviewJobId;
    }
    }

Additional comment In above case, batchclass calls the future method and future method call the webservice class.

if I directly call the InsideviewPostJob from the test class, deployment works fine.

look at below test class that directly calls the webservice callout class.

@istest(seealldata=true)
public class InsideViewPostJob_Test {
    static testmethod void InsideViewPostJobTest(){


         //Create User
        User Usr = new User();
        Usr.Username = 'testxxx@inventivhealth.com';
        Usr.LastName = 'x'; 
        Usr.Email = 'testxxx@inventivhealth.com'; 
        Usr.Alias = 'testxxx'; 
        Usr.CommunityNickname = 'testxxxx';
        Usr.TimeZoneSidKey = 'America/New_York'; 
        Usr.LocaleSidKey = 'en_US'; 
        Usr.EmailEncodingKey = 'ISO-8859-1'; 
        Usr.ProfileId = ([select Id from Profile where name = 'iVH System Administrator'])[0].id;
        Usr.LanguageLocaleKey = 'en_us';
        Usr.iVH_Business_Unit__c = 'Adheris Health';
        insert usr; 

     system.runas(usr){
            test.startTest();
                StaticResourceCalloutMock Mock = new StaticResourceCalloutMock();
                mock.setStaticResource('PostJobResp');
                mock.setstatusCode(200);
                mock.setStatus('OK');
                mock.setHeader('Accept', 'application/json');
                test.setMock(HttpCalloutMock.class, Mock);
                string ivCompanyID = '12345';
                string EndpointURL = 'https://api.insideview.com/api/v1/company/job';     
                InsideviewPostJob.IVPostRequest(EndpointURL, ivCompanyID);
                InsideViewPostResp postResp = new InsideViewPostResp();
            test.stopTest();    
        } 

    }   

}
  • Is your test class using seealldata=true annotation or seealldata=false or nothing on the first line? If so, what version api is the test class? Between orgs there can be data differences, best practice being seealldata=false. Otherwise there could be a class or something missing in the deployment changeset to production that only test has? Could run a compare between orgs of the code-base too with eclipse. – Mike Katulka Jan 14 '16 at 4:35
  • 1
    Are you also migrating the static resource along with the class? – Salesforcesmarty Jan 14 '16 at 4:50
  • Did you look at the logs? Is the Catch block being hit. If so that would be the reason for res to be null. Does you batch class implement Database.allowsCallouts – Eric Jan 14 '16 at 6:22
  • @MikeKatulka, Thanks for your response. Please look at my additional comment. i tried with seealldata=false and true, it is not working.. if test class directly calls the webservice callout class, deployment work fine... but when test class call the batchable class, batchable class calls the future method and future method call webservice callout.. it deployment fails.. looking forward for your help. – Razu Jan 15 '16 at 14:06
  • @Eric, Thanks for your response. Please look at my additional comment. i tried with seealldata=false and true, it is not working.. if test class directly calls the webservice callout class, deployment work fine... but when test class call the batchable class, batchable class calls the future method and future method call webservice callout.. it deployment fails.. looking forward for your help. Yes, batchclass does have Database.allowCallouts – Razu Jan 15 '16 at 14:07
0

Salesforcemarty,MkeKatulla,

Thanks for the response for my query. Your counter questions helped me in my analysis.

Finally it worked.

Here is the answer. In Fullcopy, webservice callout from schedulable/batch class works when you unit test (test class), if your try to deploy the same testclass fails.

Earlier code: in test class seealldata = false. few insert/update before test.startTest(). Between starttest() and stoptest(), I have put StaticResourceCalloutMock and called the batch class. It was giving error 'Pending work' during deployment. It works in fullcopy.

Working code in Test class seealldata = true. removed all insert/update before starttest() kept the code between starttest() and stoptest() as it is..

Now deployment works..

My understanding on having DML operation before starttest() was WRONG.

  • :) Great! My guess would be that your sandbox has been upgraded to Spring16 release. There is an obvious difference in behavior the way you had it. You seem to have figured out how to modify the code so it works in both places. Do you have the blue butterfly logo with 16 in the sandbox? If so, then production is an older release. In Spring16 I've been seeing a lot of changes around the unit tests, especially test.starttest and test.stoptest. Semi-related, code-base has changed: docs.releasenotes.salesforce.com/en-us/spring16/release-notes/… – Mike Katulka Jan 17 '16 at 0:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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