0

I have my REST integration working, and when I test it myself everything seems to be going ok, but I'm having problems with the TEST class and getting the error

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

Test method

    @isTest static  void testRestSalesData() {

        Account acct = new Account(name = 'test');
    insert acct;
    Sales_Data__c data = new Sales_Data__c(account__c = acct.id, Sales_Id__c='1234vx', Date__C = system.today() );
    // Set mock callout class 
    Test.setMock(HttpCalloutMock.class, new SalesDataCallOutMock()); 
    //   This causes a fake response to be sent
    //  from the class that implements HttpCalloutMock. 
   HttpResponse response =RestSalesData_CLASS.doRest();        
   // Call method to test
   HttpResponse result = RestSalesData_CLASS.doRest();   
   List<Sales_Data__C> currentList = RestSalesData_CLASS.getSalesData();
  RestSalesData_CLASS.processSalesData(result, currentList);

}   

Callout mock

    // Implement this interface method
global HTTPResponse respond(HTTPRequest request) {
    // Create a fake response
    HttpResponse response = new HttpResponse();
    response.setHeader('Content-Type', 'application/json');
    response.setBody('[{"TransDate":"2017-01-01","Sales":"161776","InvoiceNo":"C017665","CustNm":"Coomber, Skip","CustNo":"Coomber, Skip","ProductGroup":"APCCSERV","ProdNo":"WAP","ProductName":"AP Rental Space & Equipment","BrandDesc":null,"FullUnit":"-1","StandardCost":"0","UnitCost":"-85.36","PostYear":"2016","PostMnth":"7","Tier":null,"Varietal":null,"VintYear":null,"ShipState":"CA","ExtendedCost":"0","MFSellingUnit":"EACH"},{"TransDate":"2017-01-01","Sales":"161782","InvoiceNo":"C017670","CustNm":"Prison Break Vintners","CustNo":"Prison Break Vintners","ProductGroup":"APCCSERV","ProdNo":"WAP","ProductName":"AP Rental Space & Equipment","BrandDesc":null,"FullUnit":"-1","StandardCost":"0","UnitCost":"-332.9","PostYear":"2016","PostMnth":"7","Tier":null,"Varietal":null,"VintYear":null,"ShipState":"CA","ExtendedCost":"0","MFSellingUnit":"EACH"},{"TransDate":"2017-01-01","Sales":"161787","InvoiceNo":"C017675","CustNm":"Prison Break Vintners","CustNo":"Prison Break Vintners","ProductGroup":"APCCSERV","ProdNo":"WAP","ProductName":"AP Rental Space & Equipment","BrandDesc":null,"FullUnit":"-1","StandardCost":"0","UnitCost":"332.9","PostYear":"2016","PostMnth":"7","Tier":null,"Varietal":null,"VintYear":null,"ShipState":"CA","ExtendedCost":"0","MFSellingUnit":"EACH"}]');
    response.setStatusCode(200);
    return response;        
}

And the main class. Where basically I query my object in SF, query the REST interface, and then update if there are additions

    public class RestSalesData_CLASS {

    public static void updateSalesData() {
        List<Sales_Data__C> currentList = getSalesData();
        HttpResponse response =doRest();
        processSalesData(response, currentList);
    }


    public static List<Sales_Data__C> getSalesData() {
             List<Sales_Data__C> currentList = 
             [SELECT Brand__c, Cases__c, Date__c, Distributor__c, Extended_Cost__c,
             Invoice_No__c, Post_Month__c, Post_Year__c, Price__c, Product_Group__c, 
              AggProdGroup__c, account__c, Product_Name__c, Product_Number__c, Revenue__c,
              Sales_Id__c, Ship_State__c, Tier__c, Unit_Cost__c, Variety__c, Vintage__c
              FROM Sales_Data__c  ] ; 
        return currentList;
    }


    public static void processSalesData(HttpResponse response, List<Sales_Data__C> currentList) {
        List<SalesData> dataList = new List<SalesData>();
        if (response.getStatusCode() == 200) {
             dataList = (List<SalesData>)JSON.deserializeStrict(response.getBody(), List<SalesData>.class);
            system.debug(dataList);

        }   

        Map<String, Sales_Data__c> currentMap = new map<string, Sales_Data__c>();
        Map<String, Sales_Data__c> newMap = new map<string, Sales_Data__c>();
        for (Sales_Data__c current:currentList ) {
            currentMap.put(current.Sales_Id__c, current);
        }


        for (SalesData returned:dataList)  {
            if (!currentMap.containsKey(returned.Sales)) {
             Sales_Data__c SFData = matchSalesData(returned);
             newMap.put(returned.Sales, SFData);
            }
        }
        List<Sales_Data__c> updatedList = new List<Sales_Data__c>();
        updatedList.addAll(newMap.values());
        updatedList = AccountMatch.doAccountMatch(updatedList);
        insert(updatedList);


    }

    // Match the field names between VA and SF for the Sales Data objects
    static Sales_Data__c matchSalesData(SalesData VA) {
        Sales_Data__c SF = new Sales_Data__c();
        SF.Brand__c = VA.BrandDesc;
        SF.Cases__c = VA.FullUnit;
        SF.Date__c = VA.TransDate;
        SF.Distributor__c = VA.CustNm;
        SF.CustNo__c = VA.CustNo;
        SF.Extended_Cost__c = VA.ExtendedCost;
        SF.Invoice_No__c = VA.InvoiceNo;
        SF.Post_Month__c = VA.PostMnth;
        SF.Post_Year__c = VA.PostYear;
        SF.Price__c = VA.UnitCost;
        SF.Product_Group__c = VA.ProductGroup;
        SF.Product_Name__c = VA.ProductName;
        SF.Product_Number__c = VA.ProdNo;
        //SF.Revenue = 
        SF.Sales_Id__c = VA.Sales;
        SF.Ship_State__c = VA.ShipState;
        SF.Tier__c = VA.Tier;
        SF.Unit_Cost__c = VA.StandardCost;
        SF.Variety__c = VA.Varietal;
        SF.Vintage__c = ''+VA.VintYear;
        return SF;
     }


  Class SalesData {
        Date TransDate;
        String Sales;
        String InvoiceNo;
        String CustNm;
        String CustNo;
        String ProductGroup;
        String ProdNo;
        String ProductName;
        String BrandDesc;
        Decimal FullUnit;
        Decimal StandardCost;
        Decimal UnitCost;
        Integer PostYear;
        Integer PostMnth;
        String Tier;
        String Varietal;
        String ShipState;
        Integer VintYear;
        Decimal ExtendedCost;
        String MFSellingUnit;

    } // end the salesData class    

    // Query Vintners Advantage through PHP to ODBC connect then return a SalesData object where the fields match the names from VA.
    public static HttpResponse doRest() {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('http://hq.terravant.com/RESTTest.php');
        request.setMethod('GET');
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        // Set the body as a JSON object
      //  request.setBody('{"name":"mighty moose"}');
        HttpResponse response = http.send(request);
        return response;        
    } // end the rest method



}

1 Answer 1

2

This is explained in Performing DML Before Mock Callouts. You must use Test.startTest, followed by Test.setMock, followed by your callout.

The following should work:

@isTest static  void testRestSalesData() {
    Account acct = new Account(name = 'test');
    insert acct;
    Sales_Data__c data = new Sales_Data__c(account__c = acct.id, Sales_Id__c='1234vx', Date__C = system.today() );
    // Allow us to make a callout
    Test.startTest();
    // Set mock callout class 
    Test.setMock(HttpCalloutMock.class, new SalesDataCallOutMock()); 
    //   This causes a fake response to be sent
    //  from the class that implements HttpCalloutMock. 
    HttpResponse response =RestSalesData_CLASS.doRest();        
    List<Sales_Data__C> currentList = RestSalesData_CLASS.getSalesData();
    RestSalesData_CLASS.processSalesData(result, currentList);
    Test.stopTest();
    // Make sure you add assertions here!
}
1
  • That was it thanks. They really should add that too the trail head.
    – Krone
    Jan 11, 2017 at 2:02

You must log in to answer this question.

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