4

Actually there are many answers for this error "System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out", I tried all possible solutions, but couldn't solve my problem so I am posting this question.

I have a class where I'm doing web service callouts, but I'm invoking that class through a trigger. Everything is working fine and I'm happy, but it is in a sandbox that I'm trying to move to production. I'm facing a problem in the test class, so kindly help me on this.

In all the solutions I saw it says you have to complete the DML operation and then call Callouts or they also said to use @future to make the call asynchronous.

Here are my class, trigger and test class:

My class:

public class DN_send_sms{
    @Future(callout=true)
    public static void DN_SMS(string mobile,string name,string Slabname,string psAmountvalue,
        string status,string duedate) {
        // list<account> acc=[SELECT Id,Phone FROM Account where id=:conId];

        String Username ='ab@xyx.com';
        String Password = '321';
        String TempID;
        String MobileNo=mobile;
        String SenderID = 'ABC';
        String F1;
        String F2;
        String F3;
        String F4;

        if(status == 'Paid')
        {
            TempID = '20000' ;
            F1 = name + ' ';
            F2 = Slabname;
            F3 = psAmountvalue;
        }
        else if(status=='Not - Paid')
        {
            TempID = '21873' ;
            F1 = name;
            F2 = Slabname;
            F3 = duedate;
        }

        String postData = 'username=' + Username + '&pass=' + Password 
            + '&dest_mobileno=' + MobileNo +'&senderid=' + SenderID + '&tempid=' 
            + TempID +'&F1=' + F1 + '&F2=' + F2+ '&F3=' + F3 + '&F4=' + F4;

        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://123.56.01.01/blank/sms/user/urlsmstemp.php?'+postdata);
        req.setMethod('GET');
        system.debug(req);
        Http h = new Http();
        HttpResponse res = h.send(req);

        system.debug(res);
        //return res;
    }
}

My Trigger to call class

trigger DN_Generated on Debit_Note__c (after insert, after update) {

    for (Debit_Note__c DN : trigger.new){
        if(Trigger.IsInsert){
            DN_send_sms.DN_SMS(DN.Account_Phone__c,DN.Account_Name__c,Dn.Payment_Schedule_Name__c,
                string.valueof(Dn.Payment_Schedule_Value__c),DN.Debit_Note_Status__c,
                string.valueof(Dn.Due_Date__c));
        }

        // user u=[SELECT Alias,Id,MobilePhone,Name,Phone,ProfileId FROM User WHERE Id =: '0059000000101C6'];
        If(Trigger.isUpdate){

            if(trigger.oldmap.get(Dn.id).Debit_Note_Status__c!=DN.Debit_Note_Status__c)
            {
                DN_send_sms.DN_SMS(DN.Account_Phone__c,DN.Account_Name__c,Dn.Payment_Schedule_Name__c,
                    string.valueof(Dn.Pending__c),DN.Debit_Note_Status__c,string.valueof(Dn.Due_Date__c));
            }

        }
    }

}

Test class for trigger and class

@isTest(SeeAllData=true)
public class test_DN_SMS_Generated{
    public static testmethod void test_DN_SMS(){
        //user ur = [select id,Name from user where id=:'0059000000101C6'];
        Account acc = new Account();
        acc.name = 'Acc1';
        acc.Status__c = 'new';
        acc.Custom_AN__c = 1;
        acc.Project_Interested__c = 'atrium';
        acc.Phone1__c = '8015825000';
        acc.Email__c = 'sam@gmail.com';
        insert acc;

        Potential__c pot = new Potential__c();
        pot.name = 'Sam';
        pot.Account__c = acc.id;

        insert pot;

        user u = [SELECT Alias,Id,MobilePhone,Name,Phone FROM User where Alias=:'Asing'];

        string mobile = acc.Phone1__c;
        string name = acc.name = 'Acc1';
        string status = 'Planned';
        string Uname = u.name;
        string Umobile = u.MobilePhone;
        string Dateon;

        //Test.startTest();
        sitevistsendsms.sitevistsendsms1(mobile,name,status,dateon,Uname,Umobile);
        String Username = 'abc@xyz.com';
        String Password = '321';
        String TempID = '20000' ;
        String MobileNo = mobile;
        String F1 = name;
        String SenderID = 'UNI';
        String F2 = status;
        String F3 = umobile;
        string F4;
        String postData = 'username=' + Username + '&pass=' + Password + '&dest_mobileno=' 
            + MobileNo +'&senderid=' + SenderID + '&tempid=' + TempID+'&F1=' + F1+ '&F2=' 
            + F2+ '&F3=' + F3;

        Debit_Note__c DN = new Debit_Note__c();
        DN.name = 'DN_test';
        DN.Account__c = acc.id;
        DN.Debit_Note_Status__c = 'Paid';
        Insert DN;

        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new Stubby());
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://123.56.01.01/blank/sms/user/urlsmstemp.php?'+postdata);
        req.setMethod('GET');
        Http h = new Http();
        HttpResponse res = h.send(req);
        //system.debug(res);
        test.stopTest();    
    }
}

This is the error which I'm facing:

Error Message : System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.

Stack Trace : Class.test_DN_SMS_Generated.test_DN_SMS: line 57, column 1

4

Looks like you have the right components in the test but in the wrong order?

You're using the Test.setMock() after the Insert DN; (and that insert has the side-effect of making the callout).

Read through http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex_testing.htm carefully. It doesn't involve a trigger but principle is the same - configure the mock before actually using the webservice :)


Alternatively a quick & dirty job (won't get you whole code coverage though) is to wrap the critical part of the method in an if statement:

HttpResponse res;
if(!Test.isRunningTest()){
    res = h.send(req);
}
return res;
  • You mean Like This ??? Test.startTest(); Test.setMock(HttpCalloutMock.class, new Stubby()); HttpRequest req = new HttpRequest(); req.setEndpoint('123.56.01.01/blank/sms/user/urlsmstemp.php?'+postdata); req.setMethod('GET'); Http h = new Http(); HttpResponse res = h.send(req); Debit_Note__c DN = new Debit_Note__c(); DN.name = 'DN_test'; DN.Account__c = acc.id; DN.Debit_Note_Status__c = 'Paid'; Insert DN; test.stopTest(); – Sharat Jun 13 '14 at 5:14
  • Yep, something like that. Actually this link is even better example: salesforce.com/us/developer/docs/apexcode/Content/… – eyescream Jun 14 '14 at 9:13

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.