0

I am trying to test a REST API call, but getting

FATAL_ERROR System.JSONException: Malformed JSON: Expected '{' at the beginning of object.

Why do I get this error? How do I resolve it?

Here is my class:

public with sharing class GMSServiceDemo {

    private static String clientId ='12345'; 

    public static List<GMSDonorSearchModel.GMSDonorOutputSearchResult> doAdvancedSearch(GMSDonorSearchModel.GMSDonorInputSearch req){ 

        List<GMSDonorSearchModel.GMSDonorOutputSearchResult> results = new List<GMSDonorSearchModel.GMSDonorOutputSearchResult>();

        // Get token 
        String token = doLogin();

        // Make the service call
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setTimeout(30000);
        request.setEndpoint('https://TestEndPoint'); 

        request.setMethod('POST');
        request.setHeader( 'Authorization', 'Bearer ' + token );
        request.setHeader('Content-Type', 'application/json');
        request.setHeader('ClientId', clientId);
        request.setBody(JSON.serialize(req));
        System.debug('Request dump: ' + JSON.serialize(req));

        // Make the call
        HttpResponse response = http.send(request);
        System.debug(response);
        if( response.getStatusCode()==200){
            if (!response.getBody().contains('No data found')){ 
                System.debug('Adv Search Response: ' + response.getBody());

                results = (List<GMSDonorSearchModel.GMSDonorOutputSearchResult>)JSON.deserialize(response.getBody(), List<GMSDonorSearchModel.GMSDonorOutputSearchResult>.class);

            } else if (response.getBody().contains('No data found')){
                System.debug('No Data Found: ' + response.getStatusCode() + ': ' + response.getStatus());
              }
        }       
        else {
            System.debug('doAdvanceSearch returned the following status code: ' + response.getStatusCode() + ': ' + response.getStatus());
        }

        return results;

    }

@TestVisible
    private static String doLogin(){

        String accessToken = '';    
        String endPoint ='https://TestEndPoint2;
        String userId = 'userid';
        String passwd = 'Password'; 
        String grantType = 'password';
        System.debug('Login/tokenEndpoint: ' + endPoint);


        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(endPoint);
        request.setMethod('POST');
        request.setHeader('content-Type','application/json');
        request.setTimeout(40000); // 40 seconds
        request.setBody('grant_type=' + GrantType + '&client_Id='+ ClientId +'&username='+ userId + '&password=' + passwd );


        HttpResponse response = http.send(request);
        System.debug('Status: ' + response.getStatusCode() + ': ' + response.getStatus());
        System.debug('Body: ' + response.getBody());
        GmsAuth gms =  (GmsAuth)Json.deserialize(response.getBody(),GmsAuth.class);
        System.debug('GmsAuth dump: ' + gms);
        System.debug('GMS Access Token: ' + gms.access_token);

        return gms.access_token;            
    }

    public class GmsAuth{
        public String issued;
        public String expires;
        public String access_token;       
    }

This is my Mock Class:

    @isTest
global class GMSServiceMock implements HttpCalloutMock {

    // Implement this interface method      
    global HTTPResponse respond(HTTPRequest req) {

        System.debug('MockEndPoint: ' + req.getEndpoint());
        System.assertEquals('POST', req.getMethod());

        //create fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');

        res.setBody('{"MasterId":12345,"Name":"TestCompany","NamePrefix":"","FirstName":"","MiddleName":"","LastName":"","NameSuffix":"","AddressLine":"TestStreetAddress","City":"TestCity","State":"TX","Zip":"","EmailAddress":"", "Phone":"", "ChapterCode" :"","ChapterName":"","RegionCode":"","RegionName":"","IsDeceased":"False","SFID":""}'); //'{"example":"test"}'

        res.setStatusCode(200);
        return res;

        }
    }

This is my Test class:

@isTest
public class GMSCalloutClassTest {

    @isTest 
    static void testCallout(){

        //setmock callout class
        Test.setMock(HttpCalloutMock.class, new GMSServiceMock());

        GMSDonorSearchModel.GMSDonorInputSearch searchParams;

        GMSDonorSearchModel.GMSDonorInputSearch cfg = new GMSDonorSearchModel.GMSDonorInputSearch();
        cfg.masterId = '12345';
        cfg.accountType = 'IN';
        cfg.name = 'TestCompany';
        cfg.addressLine = 'TestStreetAddress';
        cfg.city = 'TestCity';
        cfg.state = ''; //state
        cfg.zip = '';
        cfg.phone = '';
        cfg.emailAddress = '';
        cfg.isdeceased = null;
        cfg.regionCode = '';


         List<GMSDonorSearchModel.GMSDonorOutputSearchResult> result = GMSServiceDemo.doAdvancedSearch(searchParams);


    }
2
  • I think you are missing out on one of the curly brackets in your test class.
    – Raj
    Jul 10, 2019 at 18:50
  • Thank you for the response. Could you please be more specific?
    – Ivo Dimov
    Jul 10, 2019 at 19:24

1 Answer 1

2

Your mock is returning a single object (that starts with a {) rather than an array that starts with a [) that the callout class expects.

Change the mock to e.g.:

res.setBody('[{"MasterId ... }]');

which is an array containing one object. See e.g. http://json.org/ for more detail on JSON objects and arrays.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .