MOCKING
Mock SOSL results in Unit Tests. External objects require mocking.
In Apex tests, use dynamic SOSL to query external objects. Tests that perform static SOSL queries of external objects fail. ~ Salesforce
Mock without Database insert
Mocking without inserting records to database is only posible using search
(.toSearchList
) method. This is caused by return type for find
which is returning Search.SearchResults
which cannot be constructed.
- Set Mock Id in Query declaration
public with sharing class ExampleController {
public static List<Account> searchAccountsByName(String accountName) {
return SOSL.find(accountName)
.inAllFields()
.returning(
SOSL.returning(Account.SObjectType)
)
.mockId('MockingExample')
.toSearchList()
.get(0);
}
}
- Pass list of
List<Sobject>
to SOSL class, and usingsetMock(String mockId, List<List<SObject>> records)
method. SetmockId
to target query to be mocked.
List<SObject> testAccounts = new List<Account>{ new Account(Name = TEST_ACCOUNT_NAME) };
SOSL.setMock('MockingExample', new List<List<SObject>>{ testAccounts });
- During execution Selector will return record that was set by
.setMock
method.
Assert.areEqual(TEST_ACCOUNT_NAME, result.get(0).Name);
- Full test method:
@IsTest
public class ExampleControllerTest {
private static final String TEST_ACCOUNT_NAME = 'MyAccount 1';
@IsTest
static void getAccountByName() {
List<SObject> testAccounts = new List<Account>{ new Account(Name = TEST_ACCOUNT_NAME) };
SOSL.setMock('MockingExample', new List<List<SObject>>{ testAccounts });
Test.startTest();
Account result = (Account) ExampleController.searchAccountsByName(TEST_ACCOUNT_NAME);
Test.stopTest();
Assert.areEqual(TEST_ACCOUNT_NAME, result.get(0).Name);
}
}
Mock with database insert
You can mock both search
and find
after inserting records into database.
- Set Mock Id in Query declaration
public with sharing class ExampleController {
public static List<Account> searchAccountsByName(String accountName) {
return SOSL.find(accountName)
.inAllFields()
.returning(
SOSL.returning(Account.SObjectType)
)
.mockId('MockingExample')
.toSearchList()
.get(0);
}
}
- Inserts records to database and pass
List<Id>
to SOSL class usingsetMock(String mockId, List<Id>) records
method. Remember to specifymockId
to target selected query.
List<Account> testAccounts = new List<Account>{ new Account(Name = SEARCH_TEXT) };
insert testAccounts;
SOSL.setMock('MockingExample', new List<Id>{ testAccounts.get(0).Id });
- During execution Selector will return record that was set by
.setMock
method. It will use standardTest.setFixedSearchResults
method before return statement.
SOSL Class:
if (mock.hasFixedMock(mockId)) {
Test.setFixedSearchResults(mock.getFixedMock(mockId));
}
Return in test:
List<List<SObject>> results = SOSL.find(SEARCH_TEXT)
.inAllFields()
.returning(SOSL.returning(Account.SObjectType).with(Account.Name))
.mockId('MockingExample')
.preview()
.toSearchList();
List<Account> fixedAccounts = [SELECT Name FROM Account];
Assert.isFalse(results.isEmpty(), 'Should return results for at least one SObject');
Assert.isFalse(results.get(0).isEmpty(), 'Accounts list shouldnt be empty');
Assert.isNotNull(results.get(0).get(0), 'Account should be returned');
Assert.areEqual(((Account) fixedAccounts.get(0)).Name, ((Account) results.get(0).get(0)).Name, 'Accounts name should be equal');
- Full test method:
@IsTest
static void mockFixedIds() {
// Test
List<Account> testAccounts = new List<Account>{ new Account(Name = SEARCH_TEXT) };
insert testAccounts;
SOSL.setMock('MockingExample', new List<Id>{ testAccounts.get(0).Id });
List<List<SObject>> results;
Test.startTest();
results = SOSL.find(SEARCH_TEXT)
.inAllFields()
.returning(SOSL.returning(Account.SObjectType).with(Account.Name))
.mockId('MockingExample')
.preview()
.toSearchList();
Test.stopTest();
// Verify
List<Account> fixedAccounts = [SELECT Name FROM Account];
Assert.isFalse(results.isEmpty(), 'Should return results for at least one SObject');
Assert.isFalse(results.get(0).isEmpty(), 'Accounts list shouldnt be empty');
Assert.isNotNull(results.get(0).get(0), 'Account should be returned');
Assert.areEqual(((Account) fixedAccounts.get(0)).Name, ((Account) results.get(0).get(0)).Name, 'Accounts name should be equal');
}