Uncommitted Work Pending in Test with System.runAs?

Uncommitted Work Pending in Test with System.runAs?

On September 21, 2025, Posted by , In Apex,Salesforce Training, With Comments Off on Uncommitted Work Pending in Test with System.runAs?
Uncommitted Work Pending in Test with System.runAs

Question:

I am writing a test class where I need to run the test as two different users, because the approveForm method contains a validation that prevents the creator of the form from approving it. In my test for approval, I am consistently running into the “Uncommitted work pending” issue, which causes my callout to fail.

Below is my controller code:

@AuraEnabled
public static ChangeAddressForm approveForm(Id caseId) {
    ChangeAddressForm form;
    try {
        form = getForm(caseId);
        validateForm(form);

        form.successes = new List<String>();
        form.errors = new List<String>();

        if (isValid(form)) {
            Account acc = getAccount(form.data.Scope__c);

            if (isSpecialAddress) {
                acc.Special_Address1__c = form.customerForm?.specialAddress1;
                acc.Special_Address2__c = form.customerForm?.specialAddress2;
                acc.Special_Careof__c = form.customerForm?.specialCareof;
                acc.Special_City__c = form.customerForm?.specialCity;
                acc.Special_Zipcode__c = form.customerForm?.specialZipCode;
            }
            if (isForeignAddress) {
                acc.Foreign_Address1__c = form.customerForm?.foreignAddress1;
                acc.Foreign_Address2__c = form.customerForm?.foreignAddress2;
                acc.Foreign_Address3__c = form.customerForm?.foreignAddress3;
                acc.Foreign_Country_Code__c = form.customerForm?.foreignCountryCode;
            }
            if (isNameSurname) {
                acc.LastName = form.customerForm?.lastName;
                acc.FirstName = form.customerForm.firstName;
            }

            // Webservice callout
            IntCust.UpdatePersonAccount(acc, false, isSpecialAddress, isForeignAddress);

            form.data = FormService.approveForm(form.data);
            update acc;
            form.successes.add(FormService.APPROVED_MESSAGE);
        }
    } catch (Exception e) {
        throw CommonUtil.auraException(e);
    }
    return form;
}

Here is my test method:

@isTest
static void testApproveForm() {
    Case testCase = [SELECT Id, AMF_Customer_Id_FF__c FROM Case LIMIT 1];
    Account acc = [SELECT Id FROM Account LIMIT 1];
    User creatorUser = TestDataFactory.getSysAdminUser();
    User approverUser = TestDataFactory.getTestCRMUser();

    Test.startTest();
    System.runAs(creatorUser) {
        Form__c testForm = TestDataFactory.createForm(
            testCase.Id,
            'ChangeAddress',
            acc.Id.toString(),
            'Foreign Address;Special Address',
            '{"specialZipCode":"54321","specialCity":"Updated City","specialCareof":"Updated Care","specialAddress2":"Updated Special Address 2","specialAddress1":"Updated Special Address 1","lastName":"User","foreignCountryCode":"NO","foreignAddress3":"Updated Foreign Address 3","foreignAddress2":"Updated Foreign Address 2","foreignAddress1":"Updated Foreign Address 1","firstName":"Test"}'
        );
    }

    ChangeAddressForm approvedForm;

    System.runAs(approverUser) {
        Test.setMock(HttpCalloutMock.class, new TestWSMockCustomer(true));
        approvedForm = ChangeAddressFormController.approveForm(testCase.Id);
        System.assertNotEquals(null, approvedForm); 
    }
    Test.stopTest(); 
}

When I run this test, I keep getting the “Uncommitted work pending” error. Why is this happening and how can I fix it?

Answer:

The problem comes from where Test.startTest() is placed. According to the documentation, any code that executes after calling Test.startTest() and before Test.stopTest() is assigned a new set of governor limits. However, if you perform DML (like your TestDataFactory.createForm() call) inside the startTest() scope before making a callout, Salesforce throws the “Uncommitted work pending” error because you are mixing DML with callouts.

Master Salesforce with expert-led salesforce online training at CRS Info Solutions—join our demo session now!!!

In your test method, you are creating the form record inside the Test.startTest() scope. That’s why the callout in approveForm is failing. To fix this, move the creation of the form outside the Test.startTest() block, and only wrap the actual approval (which makes the callout) inside Test.startTest() and Test.stopTest().

Here is the corrected test method:

@isTest
static void testApproveForm() {
    Case testCase = [SELECT Id, AMF_Customer_Id_FF__c FROM Case LIMIT 1];
    Account acc = [SELECT Id FROM Account LIMIT 1];
    User creatorUser = TestDataFactory.getSysAdminUser();
    User approverUser = TestDataFactory.getTestCRMUser();

    System.runAs(creatorUser) {
        Form__c testForm = TestDataFactory.createForm(
            testCase.Id,
            'ChangeAddress',
            acc.Id.toString(),
            'Foreign Address;Special Address',
            '{"specialZipCode":"54321","specialCity":"Updated City","specialCareof":"Updated Care","specialAddress2":"Updated Special Address 2","specialAddress1":"Updated Special Address 1","lastName":"User","foreignCountryCode":"NO","foreignAddress3":"Updated Foreign Address 3","foreignAddress2":"Updated Foreign Address 2","foreignAddress1":"Updated Foreign Address 1","firstName":"Test"}'
        );
    }

    ChangeAddressForm approvedForm;

    Test.startTest();
    System.runAs(approverUser) {
        Test.setMock(HttpCalloutMock.class, new TestWSMockCustomer(true));
        approvedForm = ChangeAddressFormController.approveForm(testCase.Id);
        System.assertNotEquals(null, approvedForm); 
    }
    Test.stopTest(); 
}

Explanation:

This test method verifies that the approveForm logic works correctly when the form is created by one user and approved by another, as required by the validation. First, it runs as the creator user to insert a test form record. Then inside a fresh governor limit context (Test.startTest), it switches to the approver user, sets up a mock for the external callout, and calls the controller’s approveForm method. Finally, it asserts that the returned form is not null, confirming successful execution without hitting the “Uncommitted work pending” issue.

Summing Up

This test demonstrates how to properly handle scenarios where one user creates a record and another user must approve it, while avoiding the “Uncommitted work pending” error. The key is placing DML operations, such as form creation, outside the Test.startTest scope and only executing the approval logic with callouts inside the fresh test context. This separation ensures Salesforce does not block the callout due to pending database operations.

By using System.runAs, the test simulates two different user contexts, maintaining the business rule that the creator cannot approve their own form. A mocked callout is provided so external integrations do not interfere, keeping the test self-contained and predictable. The final assertion validates that the form approval logic runs successfully, proving the fix is effective.

Unlock Your Future with Salesforce Training in Mumbai

Looking to build a successful career in Mumbai’s growing Salesforce ecosystem? CRS Info Solutions offers expert-led Salesforce online training designed to help you stand out in the competitive job market. Our program covers Salesforce Administration, Development, and the latest AI-powered modules, blending in-depth concepts with real-time projects for practical learning.

Whether you’re starting your Salesforce journey or upgrading your existing skills, our training is tailored to your goals. From mastering certification exams to preparing for interviews, we provide personalized mentorship, detailed course materials, and proven strategies for success.

Don’t wait—join our free demo session today and take the first step toward a rewarding Salesforce career in Mumbai!!!

Comments are closed.