6

Background:

VF remoting (@remoteAction) is being used to fetch data - this method is declared as Static (in order to make it available for @remoteAction). In this method, in order to make long running callout to external server, we are using Continuation as described here which makes a callback to another method which is again marked as Static (because it's being called from Static).

global class CalloutController{
    @RemoteAction
    public static Object helpSupportAgents(String body){
      ..
      Continuation searchContinuation = new Continuation(120); 
      searchContinuation.continuationMethod = 'callbackMethod';
      ....
    }
    public static Object callbackMethod(Object state){
      ...    
      ....
    }

} 

Problem

While writing test code for Continuation, we need to use below given methods of System.Test class which requires an instance of class/controller as argument. Presumably this object must be calling given callback method mentioned in Continuation instantiation and throwing error.

System.TypeException: No method 'callbackMethod()' on provided controller type.

CalloutController controller = new CalloutController();
Test.setContinuationResponse(CalloutController.requestLabel, response);
Object result = Test.invokeContinuationMethod(controller, conti);

It's obvious that error is because we can not call Static method by object of Class. Then I tried using .class as we do for interface but it does not work as well.

Test.setContinuationResponse(CalloutController.requestLabel, response);
Object result = Test.invokeContinuationMethod(CalloutController.class, conti);

Now, I'm not able to find any doc or any way to pass static class reference as argument. Any suggestion or experience? Similar issue reported here: https://developer.salesforce.com/forums/?id=9060G0000005oLoQAI

P.S: For just sake of deployment, I've called both methods separately in test class and good in terms of code coverage but still want to know best way to solve it.

  • 1
    Would be helpful if you provided more of your code. It doesn't seem to me as though there's quite enough to duplicate the exact issue you're experiencing. – crmprogdev Dec 25 '18 at 13:33
  • There are lot of unreleated code...so I just added code related to continuation already above ...but still if you need that code I can add but..i dont think it's gonna help.....as issue pertains to test class.... – Ayub Dec 26 '18 at 4:57
  • Here is source code: github.com/ayub-ansari/Continuation – Ayub Dec 26 '18 at 5:31
1

I think this is a gap in the testing framework for continuations. The problem is not that your method is static, but that the callback method does not match the method signature expected by Salesforce, which has 0 arguments.

I ended up making my methods testable with the following structure, which puts the logic into a 0 argument method, but then allows my remote action to use it by storing the state in a static variable. I hate adjusting my code to make it testable, but sometimes it seems like the only way in Salesforce. This does unfortunately leave the first method untested within the continuation flow but I couldn't find a better way, I'm not saying this is the best way to solve it!

global with sharing class ContinuationController {
    @TestVisible
    private static String currentState;

    global static Object callback(Object state) {
        currentState = (String)state;
        return callback();
    }

    global static Object callback() {
        HttpResponse response = Continuation.getResponse(currentState);
        //do whatever
    }
}

Test method:

@IsTest
static void testContinuation() {

    // Invoke the continuation by calling the action method
    Continuation con = (Continuation)ContinuationController.makeCallout();

    // Verify that the continuation has the proper requests
    Map<String, HttpRequest> requests = con.getRequests();

    System.assertEquals(1, requests.size());

    // create mock response
    HttpResponse response = new HttpResponse();
    //set body, status code etc.

    Test.setContinuationResponse(ContinuationController.currentState, response);

    // Invoke callback method
    Object result = Test.invokeContinuationMethod(new ContinuationController(), con);
}

If you have access to Salesforce support then I'd suggest logging a case and see what they say.

  • Should I log an Idea or log a case with Salesforce? – Ayub Jan 4 at 5:16
  • On second thoughts, the case might not get very far, and I suspect an idea would struggle to get enough votes to get Salesforce to look at it, but I'd vote for it - up to you! :). I've also submitted a documentation bug on this page developer.salesforce.com/docs/atlas.en-us.apexcode.meta/… to ask them to explain how to test a static continuation. – James Jan 4 at 10:32

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.