Apex – SOSL Query on Encrypted Text Field Not Working in Test Class

apexfield-level-encryptionsoslunit-test

I created an classic encrypted text field called "encryptedPIIData__c" in User object and added the User data.

I created a function that is able query out via SOSL based on the encrypted field. (Note that using SOQL query is not possible as SF prevents use of encrypted field in the WHERE clause of SOQL queries.)

public static User searchUserWithMatchingPIIData( String encryptedPIIData) {
        
        List<List<SObject>> searchPIIData = [
            FIND :encryptedPIIData IN ALL FIELDS 
            RETURNING User(id, firstName, lastName, email, username, encryptedPIIData__c) 
            WITH USER_MODE LIMIT 1]; 

        List<User> usersWithMatchingPIIData = (User[])searchPIIData[0];
        User u = usersWithMatchingPIIData[0]; 
        
        return u;
}

It is working perfectly. However when I try create an apex test class to do the test coverage :

@isTest
    static void testSearchUserWithMatchingPIIData() {
        String piiData = '4235-235235-233';
        User u = searchUserWithMatchingPIIData(piiData);
    }

when ran the test I get 'System.ListException: List index out of bounds: 0' error because the SOSL result will always result in a NULL value. Even when I System.runAs as User with "View Encrypted Data" permission, it just won't work for Apex test class. Any ideas?

TL;DR Why does the SOSL query for encrypted field work on Apex but not on Apex Test class?

Best Answer

In test classes, SOSL queries don't return anything by default. You have to define the results of the search yourself using Test.setFixedSearchResults. For example:

@isTest
public static void testSoslFixedResults() {
    Account a = new Account(Name = 'Test');
    insert a;
    List<Id> fixedSearchResults = new List<Id>();
    fixedSearchResults.add(a.Id);
    Test.setFixedSearchResults(fixedSearchResults);
    List<List<SObject>> searchList = [FIND 'Test' 
                                     IN ALL FIELDS RETURNING 
                                        Account(Id, Name WHERE Name = 'Test' LIMIT 1)];
}

See the documentation for more details: Adding SOSL Queries to Unit Tests

Related Topic