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

Test Coverage Issue with Webservice Test Class

I have a Static Webservice Method defined in a Global class. That Webservice method has a string argument (Opportuinty ID) and It is retriving Oppotunity data withing the same method and send it out with Webservice callout and also I am doing some string manipulation and DML Operation in the same webserive method . I am Calling this class through  Custom List View Button on Opportunity.  It worked really well and does what I needed. But Now my biggest problem is how to test this webservice method or Global class using TestMethod.

1) I tried to do that and I got an Error "Methods defined as TestMethod do not support Web service callouts, test skipped"
2) I tried to create httpCallOutMock interface and It give me Error "System.CalloutException: You have uncommitted work pending. Please commit   or rollback before calling out"
3) I tried to Put my DML execution before test.StartTest() then I put Test.Mock()  to call webserive out and last Test.StopTest() but This did not work  even. I don't know now what to do.   I am going to paste my Webserive method and also test class to see if I could get any help from discussion board. Thanks Guys in advanced.

$$ APEX CLASS $$

global class sendToEncompass{
 
  // @future(callout=true)
// public String EncompassMSG;
   WebService static String basicCallout(String OppID){
 
     opportunity opp = [select id, Loan_Number__c,Borrower_SSN__c, Co_Borrower_First_Name__c, Co_Borrower_Last_Name__c, Co_Borrower_SSN__c, Borrower_Email__c, Borrower_First_Name__c, Borrower_Last_Name__c, owner.email, Subject_Property_Street__c, Subject_Property_City__c, Subject_Property_Zip__c, Processing_Notes__c from Opportunity where id =:OppID];
   
     HttpRequest req = new HttpRequest();
     req.setClientCertificateName('xxx');
     req.setEndpoint('https://api.xxx.yyy....');
     req.setMethod('POST');
     req.setHeader('Content-Type', 'application/xml');
     req.setTimeout(120000);
     req.setBody(
     '<LoanEntries xmlns="xxx">' +
  '<LoanData>' +
  '<LoanField>' +
      '<field_id>CX.SALESFORCELINKIDATE</field_id>' +
      '<field_value>'+System.now().format('MM/dd/yyyy')+'</field_value>' +
    '</LoanField>' +
   '<LoanField>' +
      '<field_id>LoanOfficer</field_id>' +
      '<field_value>'+opp.owner.email+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>36</field_id>' +
      '<field_value>'+opp.Borrower_First_Name__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>37</field_id>' +
      '<field_value>'+opp.Borrower_Last_Name__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>11</field_id>' +
      '<field_value>'+opp.Subject_Property_Street__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>12</field_id>' +
      '<field_value>'+opp.Subject_Property_City__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>15</field_id>' +
      '<field_value>'+opp.Subject_Property_Zip__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>364</field_id>' +
      '<field_value>'+opp.Loan_Number__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>65</field_id>' +
      '<field_value>'+opp.Borrower_SSN__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>68</field_id>' +
      '<field_value>'+opp.Co_Borrower_First_Name__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>69</field_id>' +
      '<field_value>'+opp.Co_Borrower_Last_Name__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>97</field_id>' +
      '<field_value>'+opp.Co_Borrower_SSN__c+'</field_value>' +
    '</LoanField>' +
    '<LoanField>' +
      '<field_id>1240</field_id>' +
      '<field_value>'+opp.Borrower_Email__c+'</field_value>' +
    '</LoanField>' +
  '</LoanData>' +
'</LoanEntries>'
     );

     // req.setBody('{"CX.SALESFORCELINKIDATE":"'+System.now().format('MM/dd/yyyy')+'","LoanOfficer":"'+opp.owner.email+'", "36":"'+opp.Borrower_First_Name__c+'","37":"'+opp.Borrower_Last_Name__c+'","11":"'+opp.Subject_Property_Street__c+'","12":"'+opp.Subject_Property_City__c+'","15":"'+opp.Subject_Property_Zip__c+'","364":"'+Opp.Loan_Number__c+'","65":"'+Opp.Borrower_SSN__c+'","68":"'+opp.Co_Borrower_First_Name__c+'","69":"'+opp.Co_Borrower_Last_Name__c+'","97":"'+opp.Co_Borrower_SSN__c+'","1240":"'+opp.Borrower_Email__c+'"}');
     
     //req.setEndpoint('https://xxxyyyy....xxxx');
     //req.setMethod('GET');

     Http http = new Http();
//     try{
     HTTPResponse res = http.send(req);
     //return res.getBody();
   //  System.debug(res.getBody());
     String loanID = res.getBody();
   //  return loanID;
     system.debug('My Returned Body: '+loanID);
     if(loanID.contains('Created')){
     loanID = loanID.split(':', 14)[2];
     loanID = (loanID.split('<',39)[0]).trim();
     system.debug(loanID);
     opp.GUID__c = loanID;
   //  EncompassMSG = 'Encompass loan record is successfully created, Click ok to continue';
     }
     else{
      loanID = loanID.split(':', 14)[2];
      loanID = (loanID.split('<',39)[0]).trim();
      system.debug(loanID);
      opp.GUID__c = 'Error: ' +loanID;
      //EncompassMSG = 'Error is occured while creating Encompass record, please try again or contact support';
     }
   
     update opp;
     if((opp.GUID__c).contains('Error')){
     return 'Error is occured while creating Encompass record, please try again or contact support';
     }else{
     return 'Encompass loan record is successfully created';
     }
//   }
//   catch(System.CalloutException e){
//    return 'Request time is out, Please try again';
//   }
   }
}


$$ Test Class $$


@isTest
global class MockHttpEncompassResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        // Optionally, only send a mock response for a specific endpoint
        // and method.
      
       //sendToEncompass sE = new sendToEncompass();
     
    
     
    
      
        // Create a fake response
        HttpResponse res = new HttpResponse();
    
        res.setHeader('Content-Type', 'application/Xml');
     // res.setBody('{"CX.SALESFORCELINKIDATE":"'+System.now().format('MM/dd/yyyy')+'","LoanOfficer":"'+opp.owner.email+'", "36":"'+opp.Borrower_First_Name__c+'","37":"'+opp.Borrower_Last_Name__c+'","11":"'+opp.Subject_Property_Street__c+'","12":"'+opp.Subject_Property_City__c+'","15":"'+opp.Subject_Property_Zip__c+'","364":"'+Opp.Loan_Number__c+'","65":"'+Opp.Borrower_SSN__c+'","68":"'+opp.Co_Borrower_First_Name__c+'","69":"'+opp.Co_Borrower_Last_Name__c+'","97":"'+opp.Co_Borrower_SSN__c+'","1240":"'+opp.Borrower_Email__c+'","1222":"Loan Created:{8de3c840-cc26-4970-b10e-d441b090c50d}"}');
      //  res.setBody("":""'Loan Created :{8de3c840-cc26-4970-b10e-d441b090c50d}');
        res.setBody('{"Loan Created : ":"Loan Created :{8de3c840-cc26-4970-b10e-d441b090c50d}"}');
        System.debug('Body of webservice '+res.getBody());
       // res.setStatusCode(200); 
        return res;
    }

  @isTest static void testCallout() {
        
       Opportunity opp = new Opportunity(Name='demoTest',
                                        CloseDate=date.newInstance(2014, 4, 30),
                                        StageName='Active',
                                        Loan_Number__c='123456789101112',
                                        Borrower_SSN__c='8529518478',
                                        Co_Borrower_First_Name__c='FirstTest',
                                        Co_Borrower_Last_Name__c='LastTest',
                                        Co_Borrower_SSN__c='8526547458',
                                        Borrower_Email__c='demo@testemail.com',
                                        Borrower_First_Name__c='borrowerFirstName',
                                        Borrower_Last_Name__c='borrowerLastName',
                                        Subject_Property_Street__c='123 Main St',
                                        Subject_Property_City__c='Los Angeles',
                                        Subject_Property_Zip__c='98103',
                                        Processing_Notes__c='processingNotes');       
       Database.insert(opp);
       sendToEncompass.basicCallout(opp.id);
        
  
        // Set mock callout class
        Test.StartTest();
      
  Test.setMock(HttpCalloutMock.class, new MockHttpEncompassResponseGenerator());
        // Call method to test.
        // This causes a fake response to be sent
        // from the class that implements HttpCalloutMock.
     
    HttpRequest req = new HttpRequest();
        req.setClientCertificateName('xxx');
        req.setEndpoint('https://api.xxx/yyy');
        req.setMethod('POST');
        req.setTimeout(12000);
        Http h = new Http();
        HttpResponse res = h.send(req);
     
        String loanID = res.getBody();
        //System.debug('Response Body '+res.getBody());
        Test.stopTest();
    }
}
Ashish_SFDCAshish_SFDC

Hi , 


The mail article: http://help.salesforce.com/apex/HTViewSolution?id=000003701&.


Also see the related threads, 


The calls to DML operations must not be part of the Test.startTest/Test.stopTest block.

http://salesforce.stackexchange.com/questions/17293/system-calloutexception-you-have-uncommitted-work-pending-please-commit-or-rol


Here is the trick.
You have to make all the callouts before doing any DML.

So
This is Allowed : Callout --> DML
Not Allowed : DML --> Callout
Not Allowed : Callout --> DML ----> Callout

https://developer.salesforce.com/forums/ForumsMain?id=906F00000009AtjIAE


In that case you have to carry out the callout asynchronously - via an @future method is one way.  Do you need to use the results of the callout in your VF page?

https://developer.salesforce.com/forums/ForumsMain?id=906F000000091cRIAQ


@future annotation was added to the applyURLString() method. For my specific case it has worked perfectly.

https://developer.salesforce.com/forums/ForumsMain?id=906F000000091DPIAY


This is an error due to a programming bug in the class.  You can only make callouts when there are no pending database operations waiting.

https://success.salesforce.com/answers?id=90630000000hSThAAM



Regards,
Ashish

Ajay_SFDCAjay_SFDC
Hi there ,

I am agree with Ashish_SFDC . We can not make call out after DML . Use Mock class feature provided by salesforce in Latest release .

So your test class will be as follows :

static testMethod void TestMethodTest() {
        // TO DO: implement unit test
        // Create the necessary data  
        Test.startTest();
        Test.setMock(HttpCalloutMock.class , new MockHttpResponseGenerator()); // Create dummy response in MockHttpResponseGenerator Class
       
         // Use classname.methodname if class is global class and method is webservice static 
        Test.stopTest();
    }

Thanks ,
  Ajay