function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
PathikritPathikrit 

Custom Object__feed Test Method Implementation

Hi,

I am running into this problem while writing a test class for a service which is intented to add topic to FeedTrackedChange record posted by Salesforce automatically. The idea is to put a topic to any chatter feed posted automatically for a field which is tracked in Chatter. 
List<Custom_Object__feed> listFeed =[select Id,ParentId,CreatedDate from Custom_Object__feed where ParentId in:setIds];
                List<Topic> existingTopic = [select Id, Name from Topic where Name in:mapName.Values()];
        
                for(Topic t:existingTopic){ 
                    topicNames.add(t.Name);
                    mapTopicNameIds.put(t.Name,t.Id);
                }
                
                if(!listFeed.isEmpty()){
                    for(Custom_Object__feed feed:listFeed){
                        if(!topicNames.contains(mapName.get(feed.ParentId))){
                            Topic newTopic = new Topic();
                            newTopic.Name=mapName.get(feed.ParentId);
                            setTopic.add(newTopic);
                        }
                        else{
                            TopicAssignment newAssignment = new TopicAssignment();
                            newAssignment.TopicId=mapTopicNameIds.get(maptName.get(feed.ParentId));
                            newAssignment.EntityId=feed.Id;
                            listTopicAssignment.add(newAssignment);
                        }
                    }
                    listTopic.addAll(setTopic);
        
                    Database.insert(listTopic,false); //Insert Topic
                    for(pse__Proj__feed feed:listProjectFeed){ 
                        for(Topic t:listTopic){
                            if(t.Name==mapName.get(feed.ParentId)){
                                TopicAssignment newAssignment = new TopicAssignment();
                                newAssignment.TopicId=t.Id;
                                newAssignment.EntityId=feed.Id;
                                listTopicAssignment.add(newAssignment);
                            }   
                        }
                    }
                }    
                Database.insert(listTopicAssignment,false); //Insert Assignment
The problem is in the test class, when I update a certain field on the Custom_Object__c it does not automatically post a Custom_Object__feed entry. Here is my test code.
Boolean isChatterEnabled = Schema.SObjectType.User.isFeedEnabled();
system.assert(isChatterEnabled == true,'Feed Tracking is not enabled for the user'); //Assert 1
Boolean isChatterEnabledTask = Schema.SObjectType.Custom_Object__c.isFeedEnabled();
system.assert(isChatterEnabledTask == true,'Feed Tracking is not enabled for Project Task'); //Assert 2

Custom_Object__c c = new Custom_Object__c(Name='test');
insert c;

c.Status__c = 'In progress';
update c;


List<Custom_Object__feed> listTaskFeed = [select Id,parentId from Custom_Object__feed];
system.assert(listTaskFeed[0]!=null,'Feed not created'); //Assert 3
For me, the assertion 1 & 2 is working but the 3rd assertion fails with no records. I had faced a problem in Salesforce.com earlier where the LastModifiedDate on Custom_Object__c record is one second more than the CreatedDate on the Custom_Object__Feed record. Not sure if the same is happening here as well. If any one has a work around, it will be of great help!

Thanks in Advance!

Regards,
Pathikrit
pbattissonpbattisson
Hi Pathikrit

FeedTrackedChange records are not created during a unit test context. These records require a change on the parent record to be commited to the database, which does not happen during a unit test. 

Your best bet for testing such code is to break it into a number of different methods that do not require the records to be in the databse but instead run on generic collections of the items. You can then create dummy collections to test the method code properly.

You can read a little bit more around this limitation at the bottom of the following article (https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_data_access.htm).

Paul
PathikritPathikrit
Hi Paul,

Thanks for the suggestion. I do have different methods in my test code to separate out the insertion and the assertion of the Custom Object feed getting inserted (which evidently fails). But that didn't work out. I'm not quite sure I understand what you mean by "methods 
that do not require the records to be in the databse but instead run on generic collections of the items
".
Do you have any example of that sort I can refer to? Thanks again!

Pathikrit
pbattissonpbattisson
Hi Pathikrit

So say your method looks something like:
 
public void methodA() {
  List<Account> accs = [SELECT Id, Name FROM Account];
  for(Account acc: accs) {
    //do something
  }
}
You would instead spearate this into two methods:
public void methodA() {
  List<Account> accs = [SELECT Id, Name FROM Account];
  methodB(accs);
}

public void methodB(List<Account> accs) {
  for(Account acc: accs) {
    //do something
  }
}

In the second setup you can test method B by passing it any list of Accounts - they do not have to be ones which have been retrieved from the database. This will make your testing much quicker and easier, especially in cases such as yours. As an example you could have a method (taken from lines 4-7 in your code:
 
public void processTopics(List<Topic> topics) {
  for(Topic t : topics){ 
    topicNames.add(t.Name);
    mapTopicNameIds.put(t.Name,t.Id);
  }
}