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?

  • Is CustomAction.execute a queueable? – Pranay Jaiswal Jul 19 '18 at 16:37
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.