Free computer code on screen

Examining asynchronous @future callouts

I’ve extensively searched through documentation, Trailhead, and various resources, but I’m stuck. In my test class, I’m encountering an issue with the HttpCalloutMock method. The problem arises because the class I’m calling returns void, causing an “Illegal assignment from void to System.HttpResponse” error when trying to return the response. Unfortunately, I can’t modify the class to not be void because it involves a @future callout. Could there be another solution I’m overlooking? I’m happy to share my code if necessary, but I believe this is more of a broad question about testing @future callouts.

Edit:

Here’s the code snippet I’m struggling with:

Below is the class I’m attempting to achieve code coverage on (currently at 0% despite multiple attempts):

public class PortalQuery {
    @future (callout=true)
    public static void portalGet(String match_id){

        //set Match Record        
        Match_Record__c mr = [SELECT Id, PODs__c
        FROM Match_Record__c 
        WHERE Match_ID__c = :match_id];

        System.debug(match_id);
        System.debug(mr.Id);

        //callout to Portal API
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('url here');
        req.setMethod('GET');
        HttpResponse res = http.send(req);

        // If the request is successful, parse the JSON response.
        if (res.getStatusCode() == 200) {
            system.debug('response = ' + res.getBody());
            String jsonContent = res.getBody();
            System.debug(jsonContent);

            //call JSON Utility to help with parse
            Util_JSONParser parser = Util_JSONParser.createParser(jsonContent);

            //parse out Match Record fields for updates
            String match_algorithm_version = parser.get('match_algorithm_version').Value;
            if(match_algorithm_version != NULL){
                Decimal mav = Decimal.valueOf(match_algorithm_version);
                mr.Match_Algorithm_Version_Number__c = mav; 
            }
        }
        mr.Last_Match_API_Update__c = System.now();
        update mr;
    }
}

A RestResource that invokes a class:

@RestResource(urlMapping='/mrUpdate')
global with sharing class mrUpdate {

@HTTPPatch
//query SFDC Match Record from portal match_id
global static String updateMR(String match_id, String token){
    Match_Record__c mr = [SELECT Id, Send_POD__c
                            FROM Match_Record__c 
                           WHERE Match_ID__c = :match_id];
    System.debug('***Here is the MATCH ID*** ' + match_id);
    System.debug('!!!!Here is the TOKEN!!!!! ' + token);

    //call portal for MR fields
    if (token != 'some token'){
        PortalQuery.portalGet(match_id);
    }
    //call portal for PODs
    if (mr.Send_POD__c == TRUE){
        PortalQuery.podQuery(match_id);
    }

    return null;
    //call response method to show udpated Match Record json
    List <Match_Record__c> updatedMR = mrResponse.getUpdatedMR();
    return null;
}

}

And the test class

@isTest
public class portalQueryTest {
    @isTest 
    static void setData(){

        Match_Record__c mr = new Match_Record__c();
        List <Match_Record__c> mrList = new List <Match_Record__c>();
        String match_id = 'name';
        String token = 'token';

        Account account = new Account();
        account.Name = 'Account';
        insert account;

        Contact contact = new Contact();
        contact.FirstName = 'Contact';
        contact.LastName = 'Jones';
        contact.AccountId = account.Id;
        insert contact;

        Guardant_360_Sample__c sample = new Guardant_360_Sample__c();
        sample.Name = 'name';
        sample.Contact__c = contact.Id;
        sample.Account__c = account.Id;
        insert sample;

        mr.Name = 'name';
        mr.Match_ID__c = 'name';
        mr.Portal_Sample_ID__c = 'sample';
        mr.Last_Match_API_Update__c = System.now();

        insert mr;
        mrList.add(mr);

        POD__c pod = new POD__c();
        pod.Match_Record__c = mr.Id;
        insert pod;

        Test.startTest();
        //I am honestly totally lost at this point.  
        //I've looked at so many pages I'm not sure what to do here 
        //to get a json string into the class I'm trying to test.
        //I've tried the mockcallout, using a static resource, etc....        
        Test.stopTest();
    }
}

1 Answer

Future methods are asynchronous so they cannot return a value (hence the void return type). Instead you need to do something in the future method with your HTTP response (like put it in the database). In your test, calling Test.stopTest() will ensure that the @future method completes. Then, you can query for the result you updated in the @future method to ensure the update took place successfully.