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
Anindya ChattopadhyayAnindya Chattopadhyay 

System.CalloutException: You have uncommitted work pending in Test Class

Hi All:

I am trying to implement Bitly with a custom field in Opportunity. I am successful in getting the Bitly Url for the Opportunity field. However I am having trouble in getting test cases set up for the same. I followed the following article:

https://douglascayers.com/2015/10/21/salesforce-create-short-urls-with-bitly-process-builder-and-apex/
https://gist.github.com/DouglasCAyers/de978590b97e235a96fc

However my test method fails in static void test_shorten() in BitlyShortenURLInvocableTest, where it throws the following error:

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
Class.BitlyService.getAccessToken: line 56, column 1
Class.BitlyService.: line 12, column 1
Class.BitlyShortenURLInvocable.shortenAsync: line 25, column 1


I have got a process builder that calls the method shorten of BitlyShortenURLInvocable, on creation/update of Opportunity. My code in test_shorten is given below.
 

    Test.startTest();
    Test.setMock( HttpCalloutMock.class, new MockHttpResponse() );
    
    Opportunity job = new Opportunity();
    job.Name = 'Test Job';
    job.StageName = 'Not yet started';
    job.CloseDate = System.today() ; 
    insert job;
    Test.stopTest();
      
      
    job  = [ SELECT id, Shortened_Url__c FROM Opportunity WHERE id = :job.id LIMIT 1 ];
    
    System.assert( String.isNotBlank( job.Shortened_Url__c ) );
Any help will be much appreciated.

Regards,
Anindya


 

Saravana Bharathi 1Saravana Bharathi 1
Make sure, you are not doing callout synchronously on DML Event.

1. Try to split the actions, like inserting Opportunity and shorting the Url in different event. 
https://help.salesforce.com/articleView?id=000003701&type=1

In case, if you are not able to split it.
2. Use @future (callout = true) in the method, where you are doing your callout.
Even in the link, you have shared, its mentioned clearly about this.

Below lines mentioned in this Link https://douglascayers.com/2015/10/21/salesforce-create-short-urls-with-bitly-process-builder-and-apex/
// You can't invoke http callouts from Process Builder or Flow
// because the database transaction has not committed yet, you will get error:
// "System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out"
// To get around this then we'll actually make the call in a @Future method asynchronously.

If it helps, mark this as answer.

Thanks
Anindya ChattopadhyayAnindya Chattopadhyay
Hi Saravana:

Thanks. Look at the following class:

BitlyShortenURLInvocable.java

One method is an Invocable method and another one is Future. Invocable one calls the future. So on creation of any Opportunity, my process builder kicks in and calls the Invocable method. The process builder doesn't call the Future method which actually makes the callout.
The test code that is failing for me is this one:
 
Test.startTest();
Test.setMock( HttpCalloutMock.class, new MockHttpResponse() );

Opportunity job = new Opportunity();
job.Name = 'Test Job';
job.StageName = 'Not yet started';
job.CloseDate = System.today() ; 
insert job;
Test.stopTest();
  
  
job  = [ SELECT id, Shortened_Url__c FROM Opportunity WHERE id = :job.id LIMIT 1 ];

System.assert( String.isNotBlank( job.Shortened_Url__c ) );
I am still lost why as I am indeed calling in the Test.setMock( HttpCalloutMock.class, new MockHttpResponse() ); after Test.startTest();

Just scratching my head, no solution till now.

Any help will be much appreciated.

Regards,
Anindya