0

I invoking webservice callout from trigger and getting the error when running test

ERROR:

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
Stack Trace: Class.IBPortal_LinkMT4Account.Link_MT4AccountPort.Link_Account: line 44, column 1 Class.IBPortal_MT4LinkerWS.Link_MT4AC: line 9, column 1

TEST CLASS CODE:

@isTest
private class ADSS_CP_WS_Test {

    @isTest static void WithdrawalRequests1 () {              
        // This causes a fake response to be generated
        Date myDate = Date.today();
        Account act= new Account(
            Name='test',
            Lead_Source__c='Advertisement');
            insert act;

        ADSS_Platform_Account__c ADPA = new ADSS_Platform_Account__c(
            Name='test',
            Prefered_Currency__c='USD',
            Instance__c='default',
            Trading_Platform__c='MT4',
            Account__c=act.id,
            Client_Opening_Date__c=myDate);
            insert ADPA;
          ***ONE CALLOUT IS INVOKED HERE , HOW TO TEST THIS***

        ADSS_Platform_Account_Withdrawal_Fundig__c ad =  new ADSS_Platform_Account_Withdrawal_Fundig__c(
            Amount__c=1000,
            Platform_Transaction_comments__c='test',
            Request_Type__c='Charges',
            Client_Portal_Post_Comment__c='test',
            CCY__c='USD',
            ADSS_Platform_Account__c=ADPA.id,
            Initial_Deposit__c=false,
            Post_Transaction__c=true,
            Account_Name__c= act.id);
            insert ad;

        Test.startTest();
        Test.setMock(WebServiceMock.class, new ADSSWebServicesMockImpl());
        Test.stopTest();

    }

TRIGGER:

trigger trg_ClientPortal_Funds_Withd on ADSS_Platform_Account_Withdrawal_Fundig__c (after insert) {
    Set<Id> wreq= new Set<Id>();
    Set<Id> freq= new Set<Id>();
    Boolean callWS=false;
    Boolean callWSf=false;
    for (ADSS_Platform_Account_Withdrawal_Fundig__c  withd : trigger.new) {
        if (withd.Post_Transaction__c == TRUE && (withd.Request_Type__c == 'Withdrawal')||(withd.Request_Type__c == 'Charges')){
            wreq.add(withd.Id);
            callWS=true;
        }
        if (withd.Post_Transaction__c == TRUE && withd.Request_Type__c == 'Funding')   {
            freq.add(withd.Id);
            callWSf=true;
        }
    }
    if (callWS)
        ADSS_CP_WS.WithdrawalRequests(wreq);
    if (callWSf){
        system.debug('funding');
        ADSS_CP_WS.DepositRequests(freq);
    }
}

We are making callout after inserting record of ADSS_Platform_Account__c object from class from trigger:

public class IBPortal_MT4LinkerWS {
    @Future(callout=true)
    public static void Link_MT4AC(Set<Id> PlatformIds){
        Account ac;
        for (ADSS_Platform_Account__c ld: [select id, Name, Account__c,IB_ID__c,Instance__c from ADSS_Platform_Account__c where id in:PlatformIds]){
            ac = [select IBPortalID__c,SF_LeadID__c  from Account where id=:ld.Account__c];
            System.debug('--> IBPortal_MT4LinkerWS');
            IBPortal_LinkMT4Account.Link_MT4AccountPort stub= new  IBPortal_LinkMT4Account.Link_MT4AccountPort();
            String output = stub.Link_Account(String.valueof(ac.IBPortalID__c),ld.Name,ac.id,ld.Instance__c,ld.IB_ID__c);
            System.debug('--> Link_MT4AC '+output);
        }
    }
}

Mock response:

global class ADSSWebServicesMockImpl implements WebServiceMock {
   global void doInvoke(
           Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType) {
            System.debug('Print stub '+stub);
if (stub instanceof IBPortal_LinkMT4Account.Link_MT4AccountPort)
             {
               IBPortal_LinkMT4Account.Link_AccountResponse respElement = 
               new IBPortal_LinkMT4Account.Link_AccountResponse();
               respElement.return_x= 'Linked';
               response.put('response_x', respElement); 
             }
  if(stub instanceof AdssClientportalWS.ClientServiceSoap11) {
            else if(request instanceof AdssClientportalWS.WithdrawalRequest) {
                AdssClientportalWS.WithdrawalRequest rRequest = (AdssClientportalWS.WithdrawalRequest)request;
                AdssClientportalWS.WithdrawalResponse resp = new AdssClientportalWS.WithdrawalResponse();
                if(rRequest.amount>50){
                    resp.success = true;
                    resp.errorCode= 'ok';
                }
                else {
                    resp.success = false;
                    resp.errorCode= 'failed';
                }

               //resp.lastTrades = new List<comAdssClientportalSfapi.Trade> {new comAdssClientportalSfapi.Trade()};

               response.put('response_x', resp);
            }
    }
}

How to write test class for this scenario? what modifications are required?

1 Answer 1

0

Please refer the following workaround which splits the transaction into two separate Ajax processes. The first inserts the record and the second performs the callout and is able to update the newly inserted record.

CLASS // TestWsCallout.cls public class TestWsCallout{

Account myAccount;

public PageReference InsertRecord() {
    myAccount = new Account(name = 'Test Account');
    insert myAccount;
    // Calling a Web Service here would throw an exception
    return null;
}

public PageReference CallWebService() {

    // Execute a call to a Web Service
    HttpRequest req = new HttpRequest();
    req.setEndpoint('http://MyWebService12345678790.com?id=' + myAccount.Id);
    req.setMethod('GET');
    HttpResponse response = new Http().send(req);

    // Simulate an update
    myAccount.Name = 'Test Account 2';
    update myAccount;        
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM, 'WebService Called on New Account: ' + myAccount.Name));
    return null;
}

}

Thanks, vipul

4
  • Visualforce Page:
    – Vipul Goel
    Commented Oct 14, 2015 at 9:10
  • I am already doing that. the problem is in test class I am inserting a record and making callout. After that I am inserting child record and making callout. I want to know how to write test in this scenario
    – C0DEPirate
    Commented Oct 14, 2015 at 9:37
  • Please refer the following link : developer.salesforce.com/blogs/developer-relations/2013/03/… and see the section : Testing multiple HTTP callouts
    – Vipul Goel
    Commented Oct 14, 2015 at 9:55
  • ? 'Ajax' processes ? what are these?
    – cropredy
    Commented Oct 14, 2015 at 17:04

You must log in to answer this question.

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