5

The documentation on preparing tests for code with SOSL queries includes the comment "Additionally, the test method can call Test.setFixedSearchResults multiple times to define different result sets for different SOSL queries."

I'm wondering how to interpret that. It does not appear to queue results. I tried setting two and then issuing two SOSL queries and both got the latest result. I wonder if it's per object, i.e. you can set up to one result per object and if the query asks for that object, you get the result for that object. The code below returns the second list with two entries in both cases.

@isTest private class Test_SoslMulti {

    private static String EMAIL1 = '[email protected]';
    private static String EMAIL2 = '[email protected]';
    private static String EMAIL3 = '[email protected]';
    private static String STATE1 = 'MA';
    private static String STATE2 = 'NH';
    private static String STATE3 = 'VT';
    
    
    @testSetup static void setup() {
        list<Lead>leadList = new list<Lead>();
        leadList.add(new Lead(LastName='Test Lead 1', State=STATE1, Company='Test Company', Status='Open - Not Contacted', Email=EMAIL1)); 
        leadList.add(new Lead(LastName='Test Lead 2', State=STATE2, Company='Test Company', Status='Open - Not Contacted', Email=EMAIL2));
        leadList.add(new Lead(LastName='Test Lead 3', State=STATE3, Company='Test Company', Status='Open - Not Contacted', Email=EMAIL3));
        insert leadList;
    }
    
    static testMethod void myUnitTest() {
      
        list<Id>idList1 = new list<Id>();
        list<Id>idList2 = new list<Id>();
        idList1.add([select Id from Lead where State = :STATE1].Id); 
        idList2.add([select Id from Lead where State = :STATE2].Id); 
        idList2.add([select Id from Lead where State = :STATE1].Id); 
        Test.setFixedSearchResults(idList1);
        Test.setFixedSearchResults(idList2); 
                
        String safeValue = 'Test Lead';
        String searchQuery='FIND \'' + safeValue + '\' IN ALL FIELDS RETURNING Lead  (Id, Name)';
        System.debug('searchQuery -- ' + searchQuery); 
        List<List<SObject>>sObjectListList = search.query(searchquery);
        if (!sObjectListList.isEmpty()) { 
            List<Lead>lead1List = sObjectListList[0];
            System.debug('lead1List' + lead1List);
        }        
    

        sObjectListList = search.query(searchquery);
        if (!sObjectListList.isEmpty()) {
            List<Lead>lead2List = sObjectListList[0];
            System.debug('lead2List' + lead2List);
        }        
    
    }
    
}

2 Answers 2

8

The latest call to Test.setFixedSearchResults overwrites whatever happened before. The comment is only meant to state that you can simulate multiple SOSL searches in a single unit test. Of course, this won't help you in some situations, like when you perform multiple SOSL in the same method or trigger. Unfortunately, if that's the case, you might need to perform some mocking or dependency injection, or deal with not having 100% coverage. If there are searches on multiple objects, set all object Ids in the method at once, and the system will sort out the ID values (and the records) into the correct SOSL lists.

3
  • When you say "mocking or dependency injection" are you referring using Test.isRunningTest? Or another approach? I need some coverage on a method that calls multiple SOSL methods for different objects.
    – S.B.
    Commented May 8, 2019 at 17:17
  • 1
    @S.B. I can try to write up an example, but basically you can use the Stub API to mock/stub a method while using the unit test, avoiding the need for Test.isRunningTest. You can see fflib-apex-mocks as a starting point for learning how to do this.
    – sfdcfox
    Commented May 8, 2019 at 17:39
  • Thanks, I'll give this a read, for this project I have conditionals so I'll just invoke multiple tests to work through the method until I have sufficient coverage, although high-level Stub API seems like it might have some utility in my org.
    – S.B.
    Commented May 8, 2019 at 17:44
1

So it sound to me like you can do something like --

Test.setFixedSearchResults(...); MyClass.functionalMethodOne(); Test.setFixedSearchResults(...); MyClass.functionalMethodTwo();

But if your scenario is something where you are going to call one functional method (I use the term "functional" to mean your "real" code, not your test code) and that functional method does two SOSL queriers, there's no real way to set up the proper data using setFixedSearchResults();

I wish it worked like mocks where you pass in a method that gets called. Then you could queue a set of results. I did that for callout mocks. I have a class that allows a test method to queue a list of results then when the one functional method does several callouts, it gets the responses in the order I set them.

Some things in SF just aren't easy.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .