3

BACKGROUND

I am testing a method that results in two external calls out to an API.

I have this Apex unit test:

@isTest
public static void createInvoice_Success(){

    // arrange      
    StaticResourceCalloutMock contactMock = getStaticResourceCalloutMock(200, 'ContactsMock');
    StaticResourceCalloutMock invoiceMock = getStaticResourceCalloutMock(200, 'InvoicesMock');

    Map<String, HttpCalloutMock> mocksMap = new Map<String, HttpCalloutMock>();

    mocksMap.put('https://api.example.com/api/2.0/Contacts', contactMock);
    mocksMap.put('https://api.example.com/api/2.0/Invoices', invoiceMock);

    HttpCalloutMock mocks = new MultiRequestMock(mocksMap);

    Test.setMock(HttpCalloutMock.class, mocks);

    Appointment__c appointment = TestDataFactory.createAppointment();
    Id invoiceId = TestDataFactory.createInvoice(appointment);
    Id invoiceLineId = TestDataFactory.createInvoiceLine(invoiceId, appointment.Id);

    CustomAction.Request request = new CustomAction.Request();
    request.invoiceId = invoiceId;

    // act
    Test.startTest();
    List<CustomAction.Response> responseList = CustomAction.execute(new List<CustomAction.Request> {request});
    Test.stopTest();

    // assert
    System.assertEquals(true, responseList[0].isSuccess);
}

There is also a @testSetup method:

@testSetup
    static void testSetup () {

        insert new Custom_Settings__c(
            SetupOwnerId = Userinfo.getOrganizationId(),
            Key__c = 'XXXXXXXXXXXXXXXXXXXXXXXXX',
            Endpoint__c = 'https://api.example.com/api/2.0/'
        );

    }

Additionally, the test method uses this helper method:

private static StaticResourceCalloutMock getStaticResourceCalloutMock(Integer statusCode, String staticResourceName) {

    StaticResourceCalloutMock mock = new StaticResourceCalloutMock();

    mock.setStaticResource(staticResourceName);
    mock.setStatusCode(statusCode);
    mock.setHeader('Content-Type', 'application/json');

    return mock;
}

The class CustomAction has an Invocable Method such that it may be used by Process Builder

QUESTION

Why am I getting this error message:

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

What uncommitted work is it referring to?

What is the solution to making this unit test work?

1
  • Is CustomAction.execute a queueable? Jul 19, 2018 at 16:37

2 Answers 2

1

The issue related to the order of actions:

  1. Make a call out to the API
  2. Save the result of API call
  3. Make another call out to the API
  4. Save result of the second API call

I fixed the unit test by only doing one API call out per Invocable Method

0

Do you do some CRUD operation before doing your callout ? If this is the case, then you need to do your callout in a future method. You cannot do CRUD operations before doing a callout in the same context. Making your callout in a future method will create a separate context for your callout.

You must log in to answer this question.

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