[SalesForce] Webservice callout – Test class – not working

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();    
        } 

    }   

}

Best Answer

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.

Related Topic