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
Best Answer
Looks like you have the right components in the test but in the wrong order?
You're using the
Test.setMock()
after theInsert 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: