1

I am creating a unit test around a feed item trigger that is doing a callout. The code works as excepted, but when I do that unit test I am getting the exception You have uncommitted work pending. Please commit or rollback before calling out. Now I have my insert wrapped in Test.StartTest() so that isn't the issue. If I switch out object and do this on an account object the code works fine, but if I do a feeditem I get that exception. In my code I am doing Limits.getDMLRows() before the callout and it is showing 0. I have no email messages that are sending from a workflow either. Anyone have any idea?

trigger FeedItemTrigger on FeedItem (after insert) 
{
    SharepointApiHelper.getTheToken();
}

public class SharepointApiHelper {
    @future(callout=true)  
    public static void getTheToken()
    {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://test.sharepoint.com');
        req.setMethod('POST');
        req.setHeader('Content-Type','application/x-www-form-urlencoded');
        req.setBody('grant_type=refresh_token&client_id=d0dbeca5-1355-4167-aebb-12e9b226a814%40f982de02-e4a5-43aa-96e7-af82994ae26f&client_secret=oGNl%2fPAJtmhepPN0M4B9AdnvJO8ilIF2Ki3SC8nQ%2fxU%3d&refresh_token=IAAAALEmYzxTMJ3E-j3tcf17FljFohLOohlKOOsAcdUtEi-zi8gCilcX09G4yzUGx81hIg7FzpUlciEyWXVBJdJnI0LPuW2ewjeWufuy4RW5NhzDh6JlawV7DrBbkSDtnUMJDwk6QXMUr35OR5suWcMR31GEESkACv8YQ2sXFTcNm2Zwcm4KITwQhUxsGJBAAwuXiEaeb72T-RMAz10haBCZVyMhxULpulmMkVfdAma5bIsmJYqXkatlQ16N4yfy4ingYt0pAVjfXFZGhOm_cealO52A710CUZ9Cy0rrfXcnXZ4_uiCB3qYF03-eJN0vfmNZ0VEhZ8nmkoWFJwYmmZeOsPc&redirect_uri=https%3A%2F%2Fbushfound.sharepoint.com&resource=00000003-0000-0ff1-ce00-000000000000%2Fbushfound.sharepoint.com%40f982de02-e4a5-43aa-96e7-af82994ae26f');

        try{
            Http h = new Http();
            HTTPResponse res = h.send(req);

            if(res.getStatusCode() == 200){
                system.debug('accessTokenResponse:'+res.getBody());
            }
            else{
                throw new SharepointApiHelperException('An error occurred during creation of Access Token for Sharepoint API: ' + 'Status Code: ' + res.getStatusCode() + ' Body:' + res.getBody());
            } 
        }
        catch(Exception e){
            System.debug(e.getMessage());
            throw new SharepointApiHelperException(e.getMessage());
        }
    }
    public class SharepointApiHelperException extends Exception {}
}

@isTest
public class FeedItemTriggerTests {

    static testMethod void test_Inserting_Content_Post()
    {

        Account a = new Account();
        a.name = 'Test';
        insert a;

        String tokenJson = '{"token_type":"Bearer","access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvYnVzaGZvdW5kLnNoYXJlcG9pbnQuY29tQGY5ODJkZTAyLWU0YTUtNDNhYS05NmU3LWFmODI5OTRhZTI2ZiIsImlzcyI6IjAwMDAwMDAxLTAwMDAtMDAwMC1jMDAwLTAwMDAwMDAwMDAwMEBmOTgyZGUwMi1lNGE1LTQzYWEtOTZlNy1hZjgyOTk0YWUyNmYiLCJuYmYiOjE0NTg4NDAzNTcsImV4cCI6MTQ1ODg4MzU1NywibmFtZWlkIjoiMTAwMzAwMDA5NTVmMjNlZiIsImFjdG9yIjoiZDBkYmVjYTUtMTM1NS00MTY3LWFlYmItMTJlOWIyMjZhODE0QGY5ODJkZTAyLWU0YTUtNDNhYS05NmU3LWFmODI5OTRhZTI2ZiIsImlkZW50aXR5cHJvdmlkZXIiOiJ1cm46ZmVkZXJhdGlvbjptaWNyb3NvZnRvbmxpbmUifQ.HcMK-7CZTsqaXgoyfmP9UBqiP7lrUl4Y1dIy7-lWiNx7-TW-P1qToOw7tNJnw1LMmJFpepilZHUWD8IwxyE4rJoSMhq-_GeGSUc3vrJWyADxRcCxW2qHnXioB_x8JyeyXXqYHTFkzCP8N6tqmpnB6HUFbYlg86gXIFcRSNmOSVA_494u4dGInKYp9U46h_-Ry0KxnmqrBa-3ErcVNxVREUxkyMxeTY_trlscLLEZPlPb5fRs9bUWpoG-Ru3hrl8n6vLSL_xckAu8JIR1LFQqqtZoeFthkYt1ne6UmlPI353DB6oxH3pGowVvXTQ-9xZ7ev5pZ-y9is5tombJQaI8Ng","expires_in":"43199","not_before":"1458840357","expires_on":"1458883557","resource":"00000003-0000-0ff1-ce00-000000000000/bushfound.sharepoint.com@f982de02-e4a5-43aa-96e7-af82994ae26f"}';
        String xDigestJson = '{"d":{"GetContextWebInformation":{"__metadata":{"type":"SP.ContextWebInformation"},"FormDigestTimeoutSeconds":1800,"FormDigestValue":"0x2153703724CE3B3D8777CD45EA468B27B057B6EF21B9969FC8320F698E9BF2A65B8FD0A7CB8F145EF7C0CAF712EA571409FA03E8CAC7DA41EDFC68F92AF64C36,24 Mar 2016 17:25:58 -0000","LibraryVersion":"16.0.5117.1202","SiteFullUrl":"https://bushfound.sharepoint.com/sites/spsf","SupportedSchemaVersions":{"__metadata":{"type":"Collection(Edm.String)"},"results":["14.0.0.0","15.0.0.0"]},"WebFullUrl":"https://bushfound.sharepoint.com/sites/spsf"}}}';
        String sharePointFileJson = '{"d":{"__metadata":{"id":"https://test.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf document test.docx\')","uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')","type":"SP.File"},"Author":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/Author"}},"CheckedOutByUser":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/CheckedOutByUser"}},"EffectiveInformationRightsManagementSettings":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/EffectiveInformationRightsManagementSettings"}},"InformationRightsManagementSettings":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/InformationRightsManagementSettings"}},"ListItemAllFields":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/ListItemAllFields"}},"LockedByUser":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/LockedByUser"}},"ModifiedBy":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/ModifiedBy"}},"Properties":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/Properties"}},"VersionEvents":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/VersionEvents"}},"Versions":{"__deferred":{"uri":"https://bushfound.sharepoint.com/sites/spsf/_api/Web/GetFileByServerRelativeUrl(\'/sites/spsf/brad/sf%20document%20test.docx\')/Versions"}},"CheckInComment":"","CheckOutType":2,"ContentTag":"{E69CC0CE-9192-4316-8246-7121C69F1243},11,22","CustomizedPageStatus":0,"ETag":"\"{E69CC0CE-9192-4316-8246-7121C69F1243},11\"","Exists":true,"IrmEnabled":false,"Length":"55071","Level":1,"LinkingUrl":"https://bushfound.sharepoint.com/sites/spsf/brad/sf document test.docx?d=we69cc0ce9192431682467121c69f1243","MajorVersion":11,"MinorVersion":0,"Name":"sf document test.docx","ServerRelativeUrl":"/sites/spsf/brad/sf document test.docx","TimeCreated":"2016-03-19T00:03:15Z","TimeLastModified":"2016-03-24T17:26:00Z","Title":"","UIVersion":5632,"UIVersionLabel":"11.0","UniqueId":"e69cc0ce-9192-4316-8246-7121c69f1243"}}';
        SingleRequestMock authCall = new SingleRequestMock(200, 'OK', tokenJson, null);
    Test.startTest();
    Test.setMock(HttpCalloutMock.class, authCall);

    FeedItem contentFI = new FeedItem();
    contentFI.ParentId = a.id;
    contentFI.title = 'Content Post';
    contentFI.Body = 'Body of content post';

    insert contentFI;
    Test.stopTest();
    }   
}

@isTest

/*
    This class can be used to mock callouts for unit testing.  The url below shows how to do the test.
    http://blogs.developerforce.com/developer-relations/2013/03/testing-apex-callouts-using-httpcalloutmock.html

*/
public class SingleRequestMock implements HttpCalloutMock {
        public Integer code {get;Set;}
        public String status;
        public String bodyAsString;
        public Blob bodyAsBlob;
        public Map<String, String> responseHeaders;

        public SingleRequestMock(Integer code, String status, String body,
                                         Map<String, String> responseHeaders) {
            this.code = code;
            this.status = status;
            this.bodyAsString = body;
            this.bodyAsBlob = null;
            this.responseHeaders = responseHeaders;
        }

        public SingleRequestMock(Integer code, String status, Blob body,
                                         Map<String, String> responseHeaders) {
            this.code = code;
            this.status = status;
            this.bodyAsBlob = body;
            this.bodyAsString = null;
            this.responseHeaders = responseHeaders;
        }

        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse resp = new HttpResponse();
            resp.setStatusCode(code);
            resp.setStatus(status);
            if (bodyAsBlob != null) {
                resp.setBodyAsBlob(bodyAsBlob);
            } else {
                resp.setBody(bodyAsString);
            }

            if (responseHeaders != null) {
                 for (String key : responseHeaders.keySet()) {
                resp.setHeader(key, responseHeaders.get(key));
                 }
            }
            return resp;
        }
}
3
  • Hi Jaren welcome to SF.SE. You'd get a much more definitive answer if you posted your code. Please visit the help center and read 'How do I ask a good question". That said, have you used a Mock for your call-out? If not, that's likely the issue.
    – crmprogdev
    Commented Mar 25, 2016 at 14:01
  • Yes, I have created several mock callouts before.
    – Jaren
    Commented Mar 25, 2016 at 14:32
  • Jaren. Because your testmethod is creating data before the call out done in an async method, you get this error. See cropredysfdc.com/2014/06 for workaround
    – cropredy
    Commented Mar 26, 2016 at 5:48

2 Answers 2

1

You appear to have the mock call-outs, but I don't see the mock responses to them, thus the uncommitted work pending error message. The loop needs closed and the code you've shown doesn't appear to close it.

How does the call-out to sharepoint become a content feed item? From what I see, it's because you're posting it at the same the time to sharepoint. What's missing is the response back from sharepoint acknowledging that it's been successfully received.

5
  • The responses are tokenJson,xDigestJson, and sharePointFileJson. I didn't include the code the builds the http request. In my code there are no DML statements that happen before I callout.
    – Jaren
    Commented Mar 25, 2016 at 16:15
  • mocks.addRequestMock('http://test.sharepoint.com/auth',authCall); looks like an outbound call to me. Unless you receive an inbound call to close it, your class thinks there's "unfinished business" since you didn't get a response back from it. If you're not making the call, just assemble the Feed Item without making the mock callout and then insert it to the feed some other way; thus avoiding the problem entirely.
    – crmprogdev
    Commented Mar 25, 2016 at 16:21
  • I am making the call from my trigger. It's calling an @future method. That is why I am mocking the response.
    – Jaren
    Commented Mar 25, 2016 at 16:28
  • Your test class doesn't know or care where the calls are being made from. It just wants to do the accounting. What goes in must equal what comes out and vice versa. You can mock them both or avoid them both if they're not necessary to test the relevant code.
    – crmprogdev
    Commented Mar 25, 2016 at 16:31
  • I added all the code so you can see. Anytime I use a feeditem it fails, but if I use an account it works.
    – Jaren
    Commented Mar 25, 2016 at 16:58
0

I opened a case with salesforce and salesforce validated that this is bug on their end.

*System.CalloutException "You have uncommitted work pending..." occurs when performing a mock callout after a DML operation

The problem happens because an internal observer which tracks the email events and actions. Which is why you are noticing the error on chatter feed and not on the other objects where you have implemented a similar logic.

This bug fix is scheduled to go out by 202.0 version ( Summer Release - Safe Harbor ), kindly let me know how you would like to proceed further.

You must log in to answer this question.

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