[SalesForce] Code Coverage for JSON.Deserialize object in apex test classes in salesforce

I am writing test classes for apex classes code coverage.
In one apex class, I am sending request to a website and getting response in json format. Then I am deserializing the response string into inner-class objects. That portion is not being covered by me.

My Apex class code is:

public class SearchCompanyApex {
    public SearchResultJSON sJsonR{get;set;}
    public string myAPIKey {get; set;}
    public List<IncomeStatement> listIncomeStateValues{get;set;}

    public string result_of_httpReq {get; set;}


    public void loadPage(){
        string symbol = queryString('c');

        if(symbol !=null || symbol !='' ){                                                     
            generalInfo(symbol);    
        }
    }

    // Method that is requesting the data from website and assigning the data to variables of this class..
    private void generalInfo(string symbol){

        result_of_httpReq =  httpReq(symbol);
        sJsonR = (SearchResultJSON)JSON.deserialize(result_of_httpReq, SearchResultJSON.class);

    //=================== Not Covered code Start ================== Main is sJsonR.items[0].attributes not covered...  

        // Adding values in list to use it to save data in salesforce..  
        listIncomeStateValues = new List<IncomeStatement>{
            new IncomeStatement('Description', sJsonR.items[0].description,'Description__c'),
            new IncomeStatement('Company Title', sJsonR.items[0].title,'Name')
        };

    //=================== Not Covered code End  ===================

    }


    // Class to make a json obect containing the inoformation of all the fields of this class..
    public Class SearchResultJSON{
        public List<SearchedDocs> items;
    }

    public Class SearchedDocs{
        public string description{get;set;}
        public string title {get;set;}
        public list<list<string>> data{get;set;}
    }


    // Wrapper Class for CompaniesHouse Data 
    Public Class IncomeStatement{
        Public String Field{get;set;}
        Public String Value{get;set;}
        Public String SFField{get;set;}
        Public String SFValue{get;set;}


       // Constructor. Initializing values...
        public IncomeStatement(string Field, string Value,string SFField){
            this.Field = Field;
            this.Value = Value;
            this.SFValue = Value;
            this.SFField = SFField;
        }
    }
}

And Test Class code is:

@isTest
public with sharing class SearchCompanyApex_TestClass {

     static testMethod void myTest() {

        // Making object of class to be covered...
        SearchCompanyApex class_test = new SearchCompanyApex();

        // Making object of inner class of target class to be covered...
        SearchCompanyApex.SearchedDocs jsonobject_test = new SearchCompanyApex.SearchedDocs();
        jsonobject_test.description = 'Company description';
        jsonobject_test.title = 'Company Name';

        // Making list for different objects to map into fields...
        List<SearchCompanyApex.IncomeStatement> listJSONDocs = new List<SearchCompanyApex.IncomeStatement>();

        SearchCompanyApex.IncomeStatement list_description = new SearchCompanyApex.IncomeStatement('Description', jsonobject_test.description, 'Description__c');
        SearchCompanyApex.IncomeStatement list_company_title = new SearchCompanyApex.IncomeStatement('Company Title', jsonobject_test.title, 'Name');

        listJSONDocs.add(list_description);
        listJSONDocs.add(list_company_title);

        class_test.listIncomeStateValues = listJSONDocs;
        // Checking whether Website API key is equal to the saved key...    
        System.assertEquals(class_test.listIncomeStateValues, listJSONDocs);


        // It is the main part of this test class. It is call to "getAPIKeyMock" to avoid error : "Methods defined as TestMethod do not support Web service callouts." 
        Test.setMock(HttpCalloutMock.class, new GetAPIKeyMock(class_test.result_of_httpReq));

        // Calling the method "loadPage()" ...
        class_test.loadPage(); 


        SearchCompanyApex.SearchResultJSON jsonList_test = new SearchCompanyApex.SearchResultJSON();
        jsonList_test.items.add(jsonobject_test);

        class_test.sJsonR.items[0].title = jsonList_test.items[0].title;
        class_test.sJsonR.items[0].description = jsonList_test.items[0].description;


        // Checking whether Website API key is equal to the saved key...    
        System.assertEquals(class_test.sJsonR.items[0].title, 'Company Name');

        // Checking whether Website API key is equal to the saved key...    
        System.assertEquals(class_test.sJsonR.items[0].description, 'Company description');

    }


    // This is an inner class to handle WebService callout problems.
    private class GetAPIKeyMock implements HttpCalloutMock {
        private string returned_SJSONResult;

        public GetAPIKeyMock(string returned_SJSONResult) {
            this.returned_SJSONResult = returned_SJSONResult;
        }

        public HTTPResponse respond(HTTPRequest req) {
            // you can use System.assert here and "if" calls to check the request and affect your return if you wish

            HttpResponse res = new HttpResponse();
            res.setBody(returned_SJSONResult);
            return res;
        }
    }
}

Note: The uncovered code in shown in comments…
How can we cover this code?
Please tell me. Any help will be appreciated.

Best Answer

Im on mobile so apologies for brevity, but you can consider a few approaches. Either write a mock webservice (https://developer.salesforce.com/blogs/developer-relations/2013/03/testing-apex-callouts-using-httpcalloutmock.html)

or

take this (http://blog.wdcigroup.net/2012/08/salesforce-web-service-callout-test-class/) approach, which is to return a hardcoded result to simulate the webservice callout. Hope this points you to what you need.

Related Topic