You need to sign in to do that
Don't have an account?
Mike Jack
Testing multiple HTTP callouts. System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out.
Hi All,
I am integrating Salesforce with Box using HTTP Callouts and Box API Reference. I have written a Controller for a Visualforce page which displays Box Widget in the detail page. I am following this link and able to cover only 36% and getting an exception - System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out and test is failed.
Here is the Controller:
Here is the VF Page:
Test Class for above Controller:
Best Regards,
MJ
I am integrating Salesforce with Box using HTTP Callouts and Box API Reference. I have written a Controller for a Visualforce page which displays Box Widget in the detail page. I am following this link and able to cover only 36% and getting an exception - System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out and test is failed.
Here is the Controller:
global class BoxAccountFolderWidgetController { global string WidgetLink {set; get { return WLink; } } public string AccntId = ApexPages.currentPage().getParameters().get('id'); public Account ac = [select id, name, RecordTypeId, Box_Folder_ID__c from Account where id=:AccntId]; public string BoxFolderId = ac.Box_Folder_ID__c; public BoxRefreshToken__c BoxCS = [select id, RefreshToken__c, ClientId__c, ClientSecret__c from BoxRefreshToken__c limit 1]; public string ClientId = BoxCS.ClientId__c; public string ClientSecret = BoxCS.ClientSecret__c; public string RefreshToken = BoxCS.RefreshToken__c; public string endPointURL=''; public string AccessToken=''; public string SharedLink=''; public string WLink=''; String Response =''; global BoxAccountFolderWidgetController(ApexPages.StandardController controller) { } global void WidgetMethod() { system.debug('RefreshToken '+RefreshToken); //Getting Access Token and Refresh Token HttpRequest req = new HttpRequest(); endpointURL = 'https://api.box.com/oauth2/token'; req.setEndpoint(endPointURL); req.setMethod('POST'); req.setHeader('Content-Type','application/x-www-form-urlencoded'); req.setbody('grant_type=refresh_token'+ '&refresh_token='+RefreshToken+ '&client_id='+ClientId+ '&client_secret='+ClientSecret); req.setHeader('Accept','application/json'); Http http = new Http(); HTTPResponse res = http.send(req); Response=res.getBody(); system.debug('Response '+Response); Integer statusCode=res.getStatusCode(); // Parse JSON response to get AccessToken and RefreshToken values. JSONParser parser = JSON.createParser(Response); while(parser.nextToken() != null) { if((parser.getCurrentToken() == JSONToken.FIELD_NAME)) { String fieldName = parser.getText(); parser.nextToken(); if(fieldName == 'access_token') { AccessToken = parser.getText(); } if(fieldName == 'refresh_token') { RefreshToken = parser.getText(); } } } system.debug('AccessToken '+AccessToken); system.debug('RefreshToken '+RefreshToken); //Creating Shared Link for the Folder HttpRequest req2 = new HttpRequest(); endpointURL = 'https://api.box.com/2.0/folders/'+BoxFolderId; req2.setEndpoint(endpointURL); req2.setMethod('PUT'); req2.setHeader('Content-Type','application/x-www-form-urlencoded'); req2.setHeader('Accept','application/json'); req2.setHeader('Authorization', 'Bearer ' +AccessToken); req2.setbody('{"shared_link": {"access": "open"}}'); Http http2 = new Http(); HTTPResponse res2 = http2.send(req2); String Response2=res2.getBody(); system.debug('Response2 '+Response2); Integer statusCode2=res.getStatusCode(); // Parse JSON response to get Shared Link values. JSONParser parser2 = JSON.createParser(Response2); while(parser2.nextToken() != null) { if((parser2.getCurrentToken() == JSONToken.FIELD_NAME)) { String fieldName = parser2.getText(); parser2.nextToken(); if(fieldName == 'shared_link') { system.debug('Enter shared_link '); while(parser2.nextToken() != null) { if((parser2.getCurrentToken() == JSONToken.FIELD_NAME)) { String fieldName1 = parser2.getText(); parser2.nextToken(); if(fieldName1 == 'url') { system.debug('Enter url '+parser2.getText()); SharedLink = parser2.getText(); } } } } } } String s = SharedLink.substringAfter('s/'); system.debug('s '+s); WLink = 'https://app.box.com/embed_widget/s/'+s+'?view=list&sort=name&direction=ASC&theme=blue'; if(RefreshToken != null) { BoxCS.RefreshToken__c = RefreshToken ; update BoxCS; } } }
Here is the VF Page:
<apex:page standardController="Account" extensions="BoxAccountFolderWidgetController" action="{!WidgetMethod}" > <iframe src="{!WidgetLink}" width="1000" height="400" frameborder="0" ></iframe> </apex:page>
Test Class for above Controller:
@isTest public class Test_BoxAccountFolderWidgetController { public static testmethod void test1() { Account ac = New Account (name ='TestAccount', Box_Folder_Id__c = '8644998269'); insert ac; Apexpages.StandardController sss = new Apexpages.StandardController(ac); apexpages.currentpage().getparameters().put('id' , ac.id); BoxRefreshToken__c BoxCS = new BoxRefreshToken__c ( RefreshToken__c = 'AJtikYVgIUhEsvgPPnfPMLBvrhCtB3RCQFGon8TdWdxboJ1wt4XLUAyglMuqeVqF', ClientId__c ='pgevke65b3i6ujpqbfmhpeh0b2tx7o6r', ClientSecret__c = 'mwKeNUq8VARg6wIwzfLI84h47SLnlmnp'); insert BoxCS; Map<string,string> Headers = new Map<string,string>(); Headers.put('Content-Type', 'application/x-www-form-urlencoded'); SingleRequestMock fakeResp = new SingleRequestMock(200, 'Complete', '{"access_token":"YUBoKdFFSoosuj2xurAa2vnXqm6pUypB","expires_in":4084,"restricted_to":[],"refresh_token":"dWEDG768lQhtbIECGuYT5i9DCoq7Sd61ousFUD6Mro9FP2oxDmbU6arGdo8lXGan","token_type":"bearer"}', Headers); Test.startTest(); Map<string,string> Headers1 = new Map<string,string>(); Headers1.put('Content-Type', 'application/x-www-form-urlencoded'); Headers1.put('Authorization', 'Bearer kCEBaUaNAfqvMenkBflDgqF22pBd5Gka'); String Body1= '{"shared_link": {"access": "open"}}'; SingleRequestMock fakeResp1 = new SingleRequestMock(200, 'Complete', Body1, Headers1); Map<String, HttpCalloutMock> endpoint2TestResp = new Map<String,HttpCalloutMock>(); endpoint2TestResp.put('https://api.box.com/oauth2/token',fakeResp); endpoint2TestResp.put('https://api.box.com/2.0/folders',fakeResp1); HttpCalloutMock multiCalloutMock = new MultiRequestMock(endpoint2TestResp); Test.setMock(HttpCalloutMock.class, multiCalloutMock); BoxAccountFolderWidgetController abc = new BoxAccountFolderWidgetController(sss); abc.WidgetMethod(); Test.stopTest(); //System.assertEquals(/*check for expected results here...*/); } }Any Help is appreciated.
Best Regards,
MJ
You will have to split your logic into two parts:
- 1st method that makes the callout.
- 2nd method that does the update.
You need to make 2 different calls to the methods i.e., to say that something like method 2 will be called onComplete of 1st method.Appreciate your response.
I changed the Controller like this below by splitting into two methods as you said. But still encountering the same error when execiting the Test Class.
Performing a DML operation on a record and a callout cannot be made in the same transaction.
Said that, you cannot make make the call to second method as you are doing in line 120.
Since you are making a callout using a test class, which you will not be able to make, and you will have to mock the response.
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm
You can set some test value for the RefreshToken and make the code coverage.