function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
LogeshLogesh 

Sample Test class for controller containing SOQL query for External Object

Hi Friends,

Does anyone have sample test class for apex class which has soql query for External Objects? Kindly share.

Thanks,
Loges
SonamSonam (Salesforce Developers) 
Logesh, what is the exact issue you are facing with SOQL query and test class? Can you share the issue and test class code you have so the community can suggest better..
kamal_Raokamal_Rao
System.UnexpectedException: java.sql.SQLException: A callout failed because an Apex operation has pending uncommitted work. The Apex code needs to commit or roll back before callouts can be performed in the same transaction. Attempted callout URL: {0}
kamal_Raokamal_Rao
hi SONAM i am geting this error :
System.UnexpectedException: java.sql.SQLException: A callout failed because an Apex operation has pending uncommitted work. The Apex code needs to commit or roll back before callouts can be performed in the same transaction. Attempted callout URL: {0}

in test class i
SonamSonam (Salesforce Developers) 
I understand this error is appearing in the test class..can you please share the class code here. also check if this help doc gives you any suggestions to overcome this error:
https://help.salesforce.com/apex/HTViewSolution?id=000079772&language=en_US
kamal_Raokamal_Rao
yes this is true
Ian HandleyIan Handley
Sorry to necro this thread, but I'm getting the same error message and have not been able to find any solution. Here's my scenario:

I have an external database I'm connected to via an odata connection. It consists of a Member table and various other tables with FKs referring to the Member ID.

What I am trying to do is use the process builder to trigger an apex method to do a SOQL query against the Member table to get the ID and populate a custom field on the Contact object. Here is my code:
 
@InvocableMethod
    public static void PopulateMemberId(List<Id> contactIds) {
        Id contactId = contactIds[0];
        Contact contact = [SELECT FirstName, Lastname, Birthdate FROM Contact WHERE Id = :contactId];
        String nameDobHash = CreateNameDobHash(contact.FirstName, contact.LastName, contact.Birthdate);
        Member__x member = [SELECT Id FROM Member__x WHERE NameDobHash__c = :nameDobHash LIMIT 1];
        if (member != null) {
            contact.Diabetic_Discovery_ID__c = member.Id;
            try {
                update contact;
            } catch (DmlException e) {
                System.debug('An unexpected error has occurred: ' + e.getMessage());
            }
        }
    }

Here is the error I'm getting:
 
Error Occurred: An Apex error occurred: System.UnexpectedException: A callout failed because an Apex operation has pending uncommitted work. The Apex code needs to commit or roll back before callouts can be performed in the same transaction.

After googling this error, it seems like you cannot simply query an external data source along with other DML operations as they need to be async. However, when I move my code to a method annotated with @Future, I get this error:
 
Error Occurred: An Apex error occurred: System.AsyncException: Future method cannot be called from a future or batch method: MemberMethods.DoIt(Id)

I'm not sure what I'm supposed to do at this point. Thanks in advance for any help. 
Ian HandleyIan Handley
For anyone who finds this, I did find the solution. I was right to move everything to a method with the @Future annotation. What I was missing was a bit of code to check for an existing future operation and prevent recursion. See  lines 3-5 in my working solution:
 
@InvocableMethod
    public static void PopulateMemberId(List<Id> contactIds) {
        if (system.isFuture()) {
            return;
        }

        PopulateMemberIdFuture(contactIds);
    }

    @Future (callout=true)
    public static void PopulateMemberIdFuture(List<Id> contactIds) {
        Contact contact = [SELECT FirstName, Lastname, Birthdate FROM Contact WHERE Id = :contactIds[0]];
        String nameDobHash = CreateNameDobHash(contact.FirstName, contact.LastName, contact.Birthdate);
        Member__x member = [SELECT Id__c FROM Member__x WHERE NameDobHash__c = :nameDobHash LIMIT 1];
        if (member != null) {
            contact.Diabetic_Discovery_ID__c = String.valueOf(member.Id__c);
            try {
                update contact;
            } catch (DmlException e) {
                System.debug('An unexpected error has occurred: ' + e.getMessage());
            }
        }
    }

 
Ashish  VermaAshish Verma
Hi @logesh, Did you find solution for test class coverage of apex class that is querying External objects data??
Ashwani Kumar 163Ashwani Kumar 163
@ashish did you get the solution ?