2

I'm writing a component to handle CampaignMembers, and it will be common to have more than 10k CampaignMembers. So I'm writing my SOQL to get the campaignMembers in batches of 10K, appending them to the list.

Now, I'm working on a unit test, so I want to generate more than 20K Leads, and then more than 20k corresponding CampaignMembers. (I want at least 3 SOQL batches to make sure the logic works.)

I searched here and elsewhere and couldn't find a good way to circumvent the 10K DML rows limitation in a test. So now, I'm trying to do it with test.loadData(). So far, I'm getting System.UnexpectedException -- so I think I'm probably running into the same 10k limit.

I'm thinking I'll add a dynamic batch size to the class, so if Test.IsRunningTest(), batch size will scale down to 100 in my dynamic SOQL and in my forLoop.

Any ideas of how to test this otherwise?

4

No. You cannot do it. What you might be able to do instead is use mocking. For example a simple query mock might look like:

public virtual inherited sharing class Query
{
    static Query instance = new Query();
    public static void setMock(Query mock) { instance = mock; }

    public static List<SObject> records(List<SObject> records)
    {
        return instance.getRecords(records);
    }

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

Then, in your test, you can set a mock so that you can return records which are not in the database. That way, you can set up more than 10k records in memory, then have your mock return them.

@IsTest
class MyTest
{
    class CampaignMemberMock extends Query
    {
        final List<CampaignMember> mockRecords = new List<CampaignMember>();
        CampaignMemberMock buildRecords(Integer recordCount)
        {
            //populate mockRecords
            return this;
        }
        protected override List<SObject> getRecords(List<SObject> records)
        {
            return mockRecords;
        }
    }
    @IsTest static void testMyMethod()
    {
        final Integer recordCount = Limit.getLimitDmlRows() + 1;
        Query mock = new CampaignMemberMock().buildRecords(recordCount);

        Test.startTest();
            Query.setMock(mock);
            List<CampaignMember> records = Query.records([
                SELECT ... FROM CampaignMember
            ]);
        Test.startTest();

        system.assertEquals(recordCount, records.size(), 'Many records returned');
    }
}
  • that's a good approach -- well, best we can do, I guess. – PatMcClellan__c Feb 16 at 23:06
  • You could make the mock a bit more sophisticated by adding a per object cache (Map<SObjectType, List<SObject>>) so you can mock queries for more than one type of object. – Adrian Larson Feb 17 at 0:58

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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