I am sending only a single HTTP Request in Batch but still facing error System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

My test code is

static void test1(){
    User u = [Select Authorize__c From User Where Id = :UserInfo.getUserId()];
    u.Authorize__c = true;
    update u;
    System.debug('u is '+u);

    List<FeedItem> feedList= new List<FeedItem>();
    for (Integer i = 0; i<5;i++)
        feedList.add( new FeedItem(Body='@'+UserInfo.getName()+'Hello World'+i,ParentId = UserInfo.getUserId()));
    Test.setMock(HttpCalloutMock.class, new MirrorMockTimelinePostImpl());

    insert feedList;

My trigger code is

trigger PostFeedsToTimeLine on FeedItem (after insert) {

    BatchPublishTimeLine publishBatch = new BatchPublishTimeLine(Trigger.new,contentMap);

My Batch class code is

public class BatchPublishTimeLine implements Database.Batchable<sObject>,Database.AllowsCallouts{
    sObjectIterable iterable;
    Map<Id,User> userMap;
    Map<String,String> contentmap;

    public BatchPublishTimeLine(List<sObject> objectList,Map<String,String> contentmap){
        iterable = new sObjectIterable(objectList);
        this.userMap = new Map<Id,User>([Select Id,Name From User WHERE Authorize__c = true]);
        this.contentmap = contentmap;
    public Iterable<sObject> start(Database.BatchableContext BC){
        return iterable;
    public void execute(Database.BatchableContext BC, List<sObject> scope){
        GMirrorUtil.createTimeLine(scope, contentMap);

    public void finish(Database.BatchableContext BC){
        System.debug('Job Has been Finished');

My createTimeLine function code is

public static void createTimeLine(List<sObject> objList,Map<String,String> contentMap){    
    String timelineRes = doApiCall('xyzzz','POST','https://www.googleapis.com/mirror/v1/timeline','xxxxxxxxx');

doApiCall code is

public static String doAPICall(String postBody, String method, String endPoint, String accessToken){

    HttpRequest req = new HttpRequest();
    Http http = new Http();
    HttpResponse res;


    if(method == 'POST' || method == 'PUT')
    req.setHeader('Authorization','Bearer ' + accessToken);
    res = http.send(req);
    String result = res.getBody();
    System.debug('status code is '+res.getStatus());
    System.debug('result is'+res.getBody());
    return result;

and the Mock class code response is

global class MirrorMockTimelinePostImpl implements HTTPCalloutMock {
    global HTTPResponse respond(HTTPRequest req) {
        // Optionally, only send a mock response for a specific endpoint
        // and method.
        System.assertEquals('https://www.googleapis.com/mirror/v1/timeline', req.getEndpoint());
        System.assertEquals('POST', req.getMethod());

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"kind":"mirror#timelineItem", "id":"mockid", "created":"2013-07-31T12:07:34.882Z", "updated":"2013-07-31T12:07:34.882Z", "etag":"\\"ZECOuWdXUAqVdpmYErDm2-91GmY/NVMWuR8LJyCKttsmne9R4K8n7YI\\"", "text": "New Lead: OauthCheck EarlyAm, Google, Inc., (234) 567-8900"}');
        return res;

I am unable to figure out how using only one callout is throwing an error!

  • I'm having the same issue except it only happens when I try to deploy to production. In FC there is no error. You ever figure out exactly what was going on?
    – NSjonas
    Commented Dec 10, 2015 at 1:47

5 Answers 5


Run it with the following line commented out and see if it works..

feedList.add( new FeedItem(Body='@'+UserInfo.getName()+'Hello World'+i,ParentId = UserInfo.getUserId()));
//Test.setMock(HttpCalloutMock.class, new MirrorMockTimelinePostImpl());
Test.setMock(HttpCalloutMock.class, new MirrorMockTimelinePostImpl());

The Test.startTest statement must appear before the Test.setMock statement. Also, the calls to DML operations must not be part of the Test.startTest/Test.stopTest block.


  • unfortunately i tried this and it doesn't work. Commented Sep 26, 2013 at 5:25
  • 2
    Ok. I think there is still a bug with the DML executing a Trigger and then doing a callout. Can you try commenting out the //insert feedList and run your test class. It worked for me. The other DMLs are working fine (UPDATE User) its just the ones that have Triggers defined are causing issue. Maybe there is still an issue if we have DML that fires triggers. Commented Sep 27, 2013 at 2:40
  • above comment resolve my problem :D Commented Oct 26, 2013 at 5:32
  • 2
    commenting out the insert feedList defeats the whole purpose of this test, since the insert trigger calls the batch apex, which in turn makes the callout
    – willard
    Commented Feb 5, 2014 at 17:10

It looks like you may be updating a User record prior to the HTTP call (i.e. when the GlassUserApiSettings__c custom setting does not have a record for the current User being iterated over.

Also, you may find issues later on attempting to update a User record and a record of another type as part of a single transaction.

  • No i am not updating any user whuile testing one minute Updating writing the whole code Commented Sep 26, 2013 at 2:41
  • Now see the full code and then reply if possible.stuck badly Commented Sep 26, 2013 at 2:43
  • you can see i am only making a callout in batch class is this some thing wrong from salesforce side ?? Commented Sep 26, 2013 at 2:44

One of the main reason of this exception is that you are doing some CRUD operation (create,read,update,delete) in your code in same context of running test, means you are doing some DML operation and then doing call out in single run.

Your DML code must be outside the Test.startTest(). You can try with this structure

public static void testmethod()
  doDML(); // do some update,insert etc.. outside
  doAPiCalloutTest(); // Implemetnt MockTest and write API Call statements

One workaround can be, you skip the http.send(req) execution in main class by using Test.isRunningTest and provide fake response there by this check.

  • perhaps Test.setMock doesn't work in batch class .Please confirm and tell . i am also searching. Commented Sep 26, 2013 at 7:48
  • @user133421 setMock works everywhere. It generally fails in batch if there are some DML happens before call out
    – Ashwani
    Commented Sep 26, 2013 at 7:52
  • I have same exception Can someone help me,See the link: salesforce.stackexchange.com/questions/41440/… Commented Jun 25, 2014 at 5:50

Does your code even work outside of the test methods? You're not using Database.AllowsCallouts on your batch class definition, which is required if you want to make callouts from inside it.

Also, your batch class doesn't seem to actually leverage the mock response and looks like it's attempting to make a genuine call-out during the test.

While testing batch apex I often find it's easier to invoke the start() and execute() methods manually, this might help you as wlel.

  • Thanks for reply but still getting same error i changed it to public class BatchPublishTimeLine implements Database.Batchable<sObject>,Database.AllowsCallouts{ but still facing the same issue in code.Please help .need to resolve it . Commented Sep 26, 2013 at 4:14

So as far as I can ascertain, mock callouts and batches don't prevent the uncommitted error IF the callout is contained within the batch you are testing...see here for a longer explanation:

Testing a combination of webservice callouts and inserts

You must log in to answer this question.

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