1

I've created an Invocable Apex Class that allow us to search articles and return the resolution to the bot. The Apex class works as expected in the sandbox. However, I'm struggling to create a test class with more then 68% code coverage. Could anyone help, please?

APEX CLASS

public with sharing class Bot_SearchFAQ {
    public class FAQSearchInput{
        @InvocableVariable(required=true)
        public String sKeyword;
    }
    public class FAQSearchOutput{
        @InvocableVariable(required=true)
        public String sFAQSearchResult;
    }
    @InvocableMethod(label='Search FAQ')
    public static List<FAQSearchOutput> searchFAQ(List<FAQSearchInput> faqSearchInput) {
        String sArticleBaseUrl = getCommunityArticleBaseUrl();
        String sKeyword = faqSearchInput[0].sKeyword;
        String sQuery = 'FIND \'' + String.escapeSingleQuotes(sKeyword) + '\' IN NAME FIELDS RETURNING Knowledge_Article__kav(Id, Title, Chatbot_URL__c, Chatbot_Resolution__c WHERE PublishStatus = \'Online\' AND Language = \'en_US\' AND IsVisibleInPkb = true) WITH SNIPPET (target_length=255) LIMIT 1';
        System.debug(sQuery);
        Search.SearchResults searchResults = Search.find(sQuery);
        List<Search.SearchResult> articlelist = searchResults.get('Knowledge_Article__kav');
        System.debug('articlelist: ' + articlelist);
        String sFAQSearchResult = '';
        for (Search.SearchResult searchResult : articlelist)        {
            Knowledge_Article__kav article = (Knowledge_Article__kav)searchResult.getSObject();
            String sArticleSummary;
            //String sSnippet = searchResult.getSnippet('Knowledge_Article__kav.Resolution__c');
            String sSnippet = article.Chatbot_Resolution__c;
            sArticleSummary = summarizeArticleForBot(sArticleBaseUrl, article, sSnippet);
            System.debug('sArticleSummary: ' + sArticleSummary);
            sFAQSearchResult = sFAQSearchResult + sArticleSummary;
        }
        if (sFAQSearchResult == '') sFAQSearchResult = 'No result found.';
        List<FAQSearchOutput> faqSearchOutputs = new List<FAQSearchOutput>();
        FAQSearchOutput faqSearchOutput = new FAQSearchOutput();
        faqSearchOutput.sFAQSearchResult = sFAQSearchResult;
        faqSearchOutputs.add(faqSearchOutput);
        system.debug(faqSearchOutput);
        return faqSearchOutputs;
    }

    public static String summarizeArticleForBot(String sArticleBaseUrl, Knowledge_Article__kav article, String sSnippet){
        String sSummary, sURL;
        sURL = article.Chatbot_URL__c;
        //remove highlight HTML tag <mark>
        sSummary = 'Here is what I found: ' + sSnippet.replaceAll('<[^>]+>',' ') + '\n' + 'To read more click here:\n' + sURL + '\n';
        return sSummary;
    }
    public static string getCommunityArticleBaseUrl()
    {
        List<Network> communityNetworks = [SELECT Id FROM Network WHERE Name='Community Support'];
        String sArticleBaseUrl = '';
        if (communityNetworks.size()>0)
        {
            Network communityNetwork = communityNetworks[0];
            String sLoginUrl = Network.getLoginUrl(communityNetwork.id);
            sArticleBaseUrl = sLoginUrl.replace('/login', '/article/');
            System.debug('MyDebug - Community Login URL: ' + sLoginUrl);
            System.debug('MyDebug - Article Base URL: ' + sArticleBaseUrl);
        }
        return sArticleBaseUrl;
    }
}

TEST CLASS

@isTest
private class Bot_SearchFAQ_Test{
  @testSetup
  static void setupTestData(){   
    Knowledge_Article__kav knowledge_article_kav_Obj = new Knowledge_Article__kav(IsVisibleInPkb = true, Language = 'en_US', Title = 'Test Text?', Details__c='Test Text.', UrlName = 'UrlName760', Chatbot_Resolution__c = 'Test Text', Chatbot_URL__c = 'http://test71.com');
    Insert knowledge_article_kav_Obj;
    Knowledge_Article__kav newArticle = [SELECT Id, KnowledgeArticleId FROM Knowledge_Article__kav WHERE id=:knowledge_article_kav_Obj.Id];
    String articleId = newArticle.KnowledgeArticleId;
    KbManagement.PublishingService.publishArticle(articleId, true);
  }
  static TestMethod void test_searchFAQ_UseCase1(){
    test.startTest();

    Bot_SearchFAQ.faqSearchInput input = new Bot_SearchFAQ.faqSearchInput();
    input.sKeyword = 'Test Text?';

    List<Bot_SearchFAQ.faqSearchInput> listInput = new List<Bot_SearchFAQ.faqSearchInput>();
    listInput.add(input);

    Bot_SearchFAQ.searchFAQ(listInput);

    test.stopTest();
  }
}

CODE COVERAGE - I'm specifically not getting coverage on parts below. It looks like the test article that's being inserted doesn't get returned in any of the search results for the bot.

 Knowledge_Article__kav article = (Knowledge_Article__kav)searchResult.getSObject();
        String sArticleSummary;
        //String sSnippet = searchResult.getSnippet('Knowledge_Article__kav.Resolution__c');
        String sSnippet = article.Chatbot_Resolution__c;
        sArticleSummary = summarizeArticleForBot(sArticleBaseUrl, article, sSnippet);
        System.debug('sArticleSummary: ' + sArticleSummary);
        sFAQSearchResult = sFAQSearchResult + sArticleSummary;




public static String summarizeArticleForBot(String sArticleBaseUrl, Knowledge_Article__kav article, String sSnippet){
    String sSummary, sURL;
    sURL = article.Chatbot_URL__c;
    //remove highlight HTML tag <mark>
    sSummary = 'Here is what I found: ' + sSnippet.replaceAll('<[^>]+>',' ') + '\n' + 'To read more click here:\n' + sURL + '\n';
    return sSummary;
}
  • 1
    Welcome to SFSE! Please take the tour and read How to Ask. For testing, we have canonical-qa which contains a few questions and answers that come up quite frequently (like this one). If those questions don't help you, then it'd be really helpful to know which lines aren't covered. – Derek F Feb 5 at 10:52
  • I would specifically suggest you read this question and make some edits to clarify what you are struggling to cover. – David Reed Feb 5 at 12:17
2

You're using the Search.find() method to perform SOSL in your main class.

Unlike SOQL, SOSL queries don't automatically see data that's created in test context. (Even in production, it can take ~15 minutes for new data to be indexed for SOSL). In test context, you need to use Test.setFixedSearchResults() to provide a fixed set of search results for your SOSL queries. This will allow your queries to return results and execute the rest of your code.

You'd make this call in your existing unit test, test_searchFAQ_UseCase1(). It takes a List<Id>, so you'd first perform a Knowledge query to get a reference to your Knowledge article, and then use some collection trickery to get your List<Id> the easy way:

Test.setFixedSearchResults(new List<Id>(new Map<Id, Knowledge_Article__kav>([SELECT Id FROM Knowledge_Article__kav]).keySet()));

(You could also perform the query and manually accumulate a List<Id> of the article Ids you would like returned, but this is a quick one-liner).

  • Thanks David, I'm pretty new to Salesforce as you can probably tell. I've just read through the documentation and I'm now struggling to get the test class to save without any problems. Any advice on where I insert Test.setFixedSearchResults() thanks. – Oliver Westlake-Simm Feb 5 at 16:52
  • @OliverWestlake-Simm I've updated my answer with a suggestion that I think will work, but please let me know if you're still struggling. – David Reed Feb 5 at 16:55
  • David, thank you so much, I've got 100% code coverage! I've spent 16 hours yesterday and 10 hours today looking at this. If I ever see you in person, I'm buying you a beer! – Oliver Westlake-Simm Feb 5 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.