function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Tanner RussellTanner Russell 

Rest Mock testing

I am having trouble getting test coverage on my dynamic rest callout code, the code sets up the connection to the endpoint than passes in the arguments to the batch class which will make the callout and query the data to be updated and at the finish method it will call itself and set the next argument until the list is complete. How should I approach this from my test class this is what I have so far. Currently my Multi mock is throwing the error Http callout not supported for test methods because my mock variable is not being set. I havent had to do much REST testing so im fairly rusty here anything helps.

Test Class
@isTest
public class ImportLiveData_Test{
    @isTest
    public static void testAllCallout() {
        SingleRequestMock fakeAccountResp = new SingleRequestMock(200,
                                                         'Complete',
                                                         '[{"Name": "sForceTest1"}]',
                                                         null);
 
       /* SingleRequestMock fakeContactsResp = new SingleRequestMock(200,
                                                  'Complete',
                                                  '[{"LastName": "Test Last Name"}]',
                                                   null);*/
 
        Map<String, HttpCalloutMock> endpoint2TestResp =
                                   new Map<String,HttpCalloutMock>();
        endpoint2TestResp.put('https://myendpoint--uat.my.salesforce.com/services/apexrest/GetSOQLData?obj=Account',fakeAccountResp);
 
        
 
        HttpCalloutMock multiCalloutMock =
                                   new MultiRequestMock(endpoint2TestResp);
 
        Test.setMock(HttpCalloutMock.class, multiCalloutMock);
        Test.startTest();
        ImportLiveData.ImportData();
        Test.stopTest();
      //  System.assertEquals(/*check for expected results here...*/);
      //  
      //  
    }
}

Multi Mock
public class MultiRequestMock implements HttpCalloutMock {
    public class RESTException extends Exception {}
    Map<String, HttpCalloutMock> requests;
 
    public MultiRequestMock(Map<String, HttpCalloutMock> requests) {
        this.requests = requests;
    }
 
    public HTTPResponse respond(HTTPRequest req) {
        HttpCalloutMock mock = requests.get(req.getEndpoint());
        if (mock != null) {
            return mock.respond(req);
        } else {
            throw new RESTException('HTTP callout not supported for test methods');
        }
    }
 
    public void addRequestMock(String url, HttpCalloutMock mock) {
        requests.put(url, mock);
    }
}

Single Mock
@isTest
public class SingleRequestMock implements HttpCalloutMock {
        protected Integer code;
        protected String status;
        protected String bodyAsString;
        protected Blob bodyAsBlob;
        protected Map<String, String> responseHeaders;
 
        public SingleRequestMock(Integer code, String status, String body,
                                         Map<String, String> responseHeaders) {
            this.code = code;
            this.status = status;
            this.bodyAsString = body;
            this.bodyAsBlob = null;
            this.responseHeaders = responseHeaders;
        }
 
        public SingleRequestMock(Integer code, String status, Blob body,
                                         Map<String, String> responseHeaders) {
            this.code = code;
            this.status = status;
            this.bodyAsBlob = body;
            this.bodyAsString = null;
            this.responseHeaders = responseHeaders;
        }
 
        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse resp = new HttpResponse();
            resp.setStatusCode(code);
            resp.setStatus(status);
            if (bodyAsBlob != null) {
                resp.setBodyAsBlob(bodyAsBlob);
            } else {
                resp.setBody(bodyAsString);
            }
 
            if (responseHeaders != null) {
                 for (String key : responseHeaders.keySet()) {
                resp.setHeader(key, responseHeaders.get(key));
                 }
            }
            return resp;
        }
}

Code that will setup than initialize the batch apex execution
public class ImportLiveData {
    

    public static void ImportData(){
        string clientid = 'hidden';
        string clientS = 'hidden';
        string token = 'hidden';
        string username = 'hidden';
        String reqbody = 'grant_type=password&client_id='+clientid+'&client_secret='+clientS+'&username='+username+'&password='+token;   
        String endpoint='https://test.salesforce.com/services/oauth2/token';
        String Access_Token;
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(endpoint);
        
        request.setMethod('GET');
        request.setBody(reqbody);
        HttpResponse response = http.send(request);
        System.debug(response.getBody());
        JSONParser parser = JSON.createParser(response.getBody());
        while (parser.nextToken() != null) {
            if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'access_token')) {
                parser.nextToken();
                Access_Token = parser.getText();    
            } 
        }            

    Database.executeBatch(new ImportDataBatch('Account',Access_Token));
 
      
    }
    
    
    public static List<sObject> GetRecords(string obj,string tokses){
        Httprequest req1 = new HttpRequest();  
        req1.setEndpoint('https://MyEndpoint--uat.my.salesforce.com/services/apexrest/GetSOQLData?obj=' + obj);  
        req1.setMethod('GET');    
        req1.setHeader('Content-Type','application/json');
        req1.setHeader('Authorization','Bearer '+tokses);            
        Http http1 = new Http();
        HttpResponse res1 = http1.send(req1); 
        List<sObject> objls = (List<sObject>)JSON.deserialize(  res1.getBody() , List<sObject>.class);
     
        System.debug(objls.size());
        return objls;
    }
}
 Part of the batch that calls the REST endpoint and imports the data
 
global class ImportDataBatch implements Database.Batchable<sObject>,Database.AllowsCallouts {
    
    public List <sObject> lsObject = new List<sObject>();
    public string test;
    public string oto;
    global ImportDataBatch(string t, string o){
        //lsObject = objls;    
        test = t;     
        oto = o;    
    }
    
    global List<sObject> start(Database.BatchableContext bc) {
        
        // collect the batches of records or objects to be passed to execute
        return ImportLiveData.GetRecords(test,oto);
        
    }
    global void execute(Database.BatchableContext bc, List<sObject> records){
...

}
   global void finish(Database.BatchableContext bc){
        //The code will call itself again with the next set of data
     
        if(test.equals('Account')){
            Database.executeBatch(new ImportDataBatch('Contact',oto));
        }
...
}