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. SetmockIdto 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
.setMockmethod.
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>) recordsmethod. Remember to specifymockIdto 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
.setMockmethod. It will use standardTest.setFixedSearchResultsmethod 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');
}