Skip to main content

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.

  1. 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);
}
}
  1. Pass list of List<Sobject> to SOSL class, and using setMock(String mockId, List<List<SObject>> records) method. Set mockId 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 });
  1. During execution Selector will return record that was set by .setMock method.
Assert.areEqual(TEST_ACCOUNT_NAME, result.get(0).Name);
  1. 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.

  1. 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);
}
}
  1. Inserts records to database and pass List<Id> to SOSL class using setMock(String mockId, List<Id>) records method. Remember to specify mockId 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 });
  1. During execution Selector will return record that was set by .setMock method. It will use standard Test.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');
  1. 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');
}