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


    }
  • I think you are missing out on one of the curly brackets in your test class. – Raj Jul 10 '19 at 18:50
  • Thank you for the response. Could you please be more specific? – Ivo Dimov Jul 10 '19 at 19:24
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.

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.