0

I have a class that has 15 tested lines of code. I have a test class as well, but the class only covers 9 lines of code. After reading about FedTrackedChange objects and how they cannot be simulated test classes, I'm not sure how to make my test class give me the proper coverage. 9 of 15 lines coverage leaves me at 60%. The purpose of the class is to delete the generic line of code that posts to Account and Contact Feeds when a Lead is converted. Can anyone show me how to adjust either the test class or public class and still achieve the same result? Thanks.

/******
CLASS
******/

public class DeleteAccountFeedAndContactFeedClass {

    @future
    public static void DeleteAccountandContactFeeds(List<ID> recordIds){

        // lists to hold accountFeeds and contactFeeds to delete
        List<AccountFeed> listAccountFeedsToDelete = new List<AccountFeed>();
        List<ContactFeed> listContactFeedsToDelete = new List<ContactFeed>();

        // find accountFeed items to delete
        for(AccountFeed objFeedAcct : [SELECT Id, Type, ParentId, (select Id, FieldName from FeedTrackedChanges)
                                       FROM AccountFeed 
                                       WHERE Type = 'TrackedChange' and ParentId in: recordIds]){         

            // add accountFeeds to list
            for(FeedTrackedChange objChange : objFeedAcct.FeedTrackedChanges){
                if(objChange.FieldName == 'accountCreatedFromLead' || objChange.FieldName == 'accountUpdatedByLead'){          
                    listAccountFeedsToDelete.add(objFeedAcct);
                }
            }
        }              

        // find contactFeed items to delete
        for(ContactFeed objFeedCon :[SELECT Id, Type, ParentId, (select Id, FieldName from FeedTrackedChanges)
                                     FROM ContactFeed 
                                     WHERE Type = 'TrackedChange' and ParentId in: recordIds]){

            // add contactFeeds to list
            for(FeedTrackedChange objChangeCon : objFeedCon.FeedTrackedChanges){              
                if(objChangeCon.FieldName == 'contactCreatedFromLead' || objChangeCon.FieldName == 'contactUpdatedByLead'){
                    listContactFeedsToDelete.add(objFeedCon);   
                }
            }
        }

        // delete accountFeeds and contactFeeds
        DELETE listAccountFeedsToDelete;
        DELETE listContactFeedsToDelete;

    }//end method
}//end class

/******
TEST CLASS
******/

@isTest
private Class DeleteAcctFeedAndConFeedClassTest{

private static testMethod void myUnitTest() {

    // create a Lead
    Lead ld = new Lead(LastName='lName', FirstName='fName', Company='myCompany', Status='Contacted');

    // insert lead
    insert ld;                

    // convert lead
    Database.LeadConvert lc = new database.LeadConvert();
    lc.setLeadId(ld.id);
    lc.setDoNotCreateOpportunity(false);
    lc.setConvertedStatus('Converted');

    leadStatus convertStatus = [SELECT Id, MasterLabel, IsConverted FROM LeadStatus WHERE IsConverted = TRUE LIMIT 1];
    system.debug('Info from MasterLabel' + convertStatus.MasterLabel);
    lc.setConvertedStatus(convertStatus.MasterLabel);

    Database.LeadConvertResult lcr = Database.convertLead(lc);
    System.assert(lcr.isSuccess());

    }
}

enter image description here

  • FYI - adding (SeeAllData=TRUE) makes the test fail. – Rock Tober Mar 29 '17 at 15:33
1

Its a bit of work, but if you really want to properly cover those lines you will have to change your structure a bit:

Create a class to return the AccountFeedItems and mocking if in text context

public class queryFeedItems{

     public static AccountFeed[] getFeedItems(Id[] recordIds){

          if(test.isRunningTest())
              return mockFeedItems();
          else
              return [SELECT Id, Type, ParentId, (select Id, FieldName from FeedTrackedChanges) FROM AccountFeed WHERE Type = 'TrackedChange' and ParentId in: recordIds];

     }

     private static AccountFeed[] mockFeedItems(){
           AccountFeed[] mockItems = New AccountFeed[]{
                 New AccountFeed(.......)
           };
     }
}

then in your code use:

for(AccountFeed objFeedAcct : queryFeeditems.getFeedItems()){
   ....
}

Note The above is meant to convey a concept. You will have to build it out to be more dynamic and function across many use cases. It will however allow you to test properly when you need sObjects that cannot be created during tests.

Also, sfdcfox pointed out a good point. You will have to extend this to mock the delete as well. When mocking you will want to assert the list to delete contains the correct items in the list.

| improve this answer | |
  • But then they'll have to use try/catch blocks because the records don't really exist, and that might obscure real failures later on down the road.... – sfdcfox Mar 29 '17 at 15:58
  • @sfdcfox - True, but the concept could be extended to the delete as well mocking the delete if in test context. Of course you would have to validate the lists contained the expected items when mocking to validate the code. I bet you have a better option other than leaving it untested? – Eric Mar 29 '17 at 16:00

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.