Salesforce SOQL-Free Apex Tests with Selector Pattern

Ben Butler
2 min readSep 16, 2021

With Apex a Selector Pattern provides multiple benefits including

  • A centralized place to query once, minimizing the number of queries
  • The ability to test the queries in the Selector independent from the classes that utilize the Selector

Selector Patterns can allow for a configurable query. In the case below we configure with Custom Metadata

public class AccountSelector implements IAccountSelector {
public List<Account> selectById(List<Id> accountIds){
list<string> fieldList = new list<string>{ 'Id' };
for (Account_Selector_Field__mdt asf : Account_Selector_Field__mdt.getAll().values())
fieldList.add(asf.fieldname__c);
String accountQuery = 'SELECT {0} FROM Account WHERE Id in (\'{1}\')'
.replace('{0}',String.join(fieldList,','))
.replace('{1}',String.join(accountIds,'\',\''));
return Database.query(accountQuery);
}
}

As indicated create an interface

public interface IAccountSelector {
List<Account> selectById(List<Id> accountIds);
}

The below trigger handler class does not do anything functional but it is an example of how we can inject a Mock of the selector into the constructor. This allows query-free dml-free tests on the class.

public class AccountTriggerHandler {
IAccountSelector accountSelector;
public AccountTriggerHandler(){
accountSelector = new AccountSelector();
}

public AccountTriggerHandler(IAccountSelector anAccountSelector{
accountSelector = anAccountSelector;
}

public List<Account> getAccounts(Id accountId){
return accountSelector.selectById(new List<Id>{ accountId});
}
}

In the test, we can Mock the selection of data by creating a Mock class and generating the data we care about in the Mock.

@isTest
private class AccountTriggerHandlerTest{
static testMethod void testGetAccounts() {
AccountTriggerHandler ath = new AccountTriggerHandler(new AccountSelectorTest());
List<Account> testResults = ath.getAccounts(’0011k0000000000AAA’);
System.assertEquals(testResults[0].Id, '0011k0000000000AAA’);
}
class AccountSelectorTest implements IAccountSelector {
public List<Account> selectById(List<Id> accountIds){
return (List<Account>) JSON.deserialize(
'[{"Id":"0011k0000000000AAA","Name":"testAccount"}]'
 , List<Account>.class
);
}
}
}

The test injects a selector mock now allowing for SOQL-free apex tests. The Selector pattern limits SOQL to tests that test the selector patterns, allowing us to scale with tests that don’t need awkward workaround to queries.

--

--