0

How can the Test Coverage can be fulfilled for the Apex classes which queried for External Objects.I have written Test class just like assuming External Object behaves like a custom Object but getting error repetitively "CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: You can't create records for the object".

I used the DML statements like Database.insertAsync but no use. Gone through some articles saying that we need to mock the external object for the Apex Test coverage on External Object. If so is there document which explains about this concept.

3

Typically we just set up a simple mock for this type of testing. You can have a class which just passes records through normally, but then when you overwrite it passes whatever you choose:

public virtual inherited sharing class Query
{
    public static List<SObject> records(List<SObject> records)
    {
        return instance.passThrough(records);
    }

    static Query instance = new Query();
    @TestVisible static void setMock(Query mock) { instance = mock; }

    protected virtual List<SObject> passThrough(List<SObject> records)
    {
        return records;
    }
}

Once you've got this mocking set up, wrap your query in this method in your service:

public with sharing class MyService
{
    public static void doStuff()
    {
        for (My_External_Object__x record : Query.records([
            SELECT ... FROM My_External_Object__x
        ])){
            // logic
        }
    }
}

In your test, usage would then look like:

@IsTest
class MyTests
{
    class Mock extends Query
    {
        final List<My_External_Object__x> externalRecords;
        Mock(List<My_External_Object__x> externalRecords)
        {
            this.externalRecords = externalRecords;
        }

        protected override List<SObject> passThrough(List<SObject> records)
        {
            return externalRecords;
        }
    }

    @IsTest staticVoid testStuff()
    {
        List<My_External_Object__x> mockRecords = new List<My_External_Object__x>();
        // populate as desired

        Query.setMock(new Mock(mockRecords));

        Test.startTest();
            MyService.doStuff();
        Test.stopTest();

        // make assertions
    }
}
| improve this answer | |
  • I came across this when running into the same issue of finding a solution for testing external objects. I was able to implement this pretty well but I am curious how to handle it when my class talks to several external objects. How would the test be structured to handle multiple? Mostly confused with the class Mock extends Query section and how this would look with multiple external objects. – SBB Jan 30 at 22:07
  • @SBB When we had to support multiple objects, we built out a generic mock which would cache a Map<SObjectType, List<SObject>>. – Adrian Larson Jan 31 at 0:28
  • Thanks, I will see what I can come up with. Any of that out on a public git repo by chance? Sorry to hi-jack the question, very little info out there on unit testing external objects! – SBB Jan 31 at 1:00
  • @SBB No problem at all. I just worry posting our solution to that part of the problem might get us in hot water with legal.Trying to keep the discussion in general terms. – Adrian Larson Jan 31 at 14:49
  • If your able to answer a question directly without linking to other company resources, I have a bounty open for essentially the same question - salesforce.stackexchange.com/questions/293015/… – SBB Feb 3 at 17:05

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.