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
Ramanjot SidhuRamanjot Sidhu 

TestClass Failing - SystemInsert Error

Hi, I have a code for counting completed activities and it works well in my sandbox. However I cannot deploy it to production because the testclass keeps failing..  I get this error:

Class test_ActivityUtils
Method Name mainTest
Pass/Fail Fail
Error Message System.AssertException: Assertion Failed: Expected: 3, Actual: 0
Stack Trace Class.test_ActivityUtils.mainTest: line 86, column 1

I have bolded line 86


@isTest(seeAllData = true)
private class test_ActivityUtils {
 
    static testMethod void mainTest() {
                Account acc = new Account();
                acc.Name = 'Test Account';
                acc.Industry = 'Transportation'; 
                insert acc;
 
 try { // Perform some database operations that 
 // might cause an exception. 
 insert acc; } 
 catch(DmlException e) { // DmlException handling code here. 
 System.debug('The following exception has occurred:  ' + e.getMessage());
 
 }
        Contact c = new Contact();
        c.FirstName = 'Joe';
        c.LastName = 'Smith';
        c.AccountId = acc.Id;
        c.Email = 'ramanjot_sidhu@hotmail.com';
        insert c;

  try { // Perform some database operations that 
 // might cause an exception. 
 insert c; } 
 catch(DmlException e) { // DmlException handling code here. 
 System.debug('The following exception has occurred: ' + e.getMessage());
 }
        Opportunity o = new Opportunity();
        o.AccountId = acc.Id;
        o.StageName = 'Open';
        o.Amount = 5000.00;
        o.CloseDate = Date.today() + 7;
        o.Name = 'Test Opp';
        insert o;
 
   try { // Perform some database operations that 
 // might cause an exception. 
 insert o; } 
 catch(DmlException e) { // DmlException handling code here. 
 System.debug('The following exception has occurred: ' + e.getMessage());
 }
         
        Task[] tList = new list<task>();
        for(Integer i=0; i<3; i++) {
            Task t = new Task();
            t.Status = 'Not Started';
            t.Priority = 'Normal';
            t.Type = 'Scheduled Call Back';
            if(i==0) t.WhatId = acc.Id;
            if(i==1) t.WhatId = o.Id;
            if(i==2) t.WhoId = c.Id;
            tList.add(t);
 
          
          Event[] eList = new list<event>();
          {
            Event e = new Event();
            e.StartDateTime = DateTime.now() + 7;
            e.EndDateTime = DateTime.now() + 14;
            if(i==0) e.WhatId = acc.Id;
            if(i==1) e.WhatId = o.Id;
            if(i==2) e.WhoId = c.Id;
             eList.add(e);
        }
        insert tList;
        insert eList;
 
   try { // Perform some database operations that 
 // might cause an exception. 
 insert tlIST; } 
 catch(DmlException e) { // DmlException handling code here. 
 System.debug('The following exception has occurred:' + e.getMessage());
 }
 
    try { // Perform some database operations that 
 // might cause an exception. 
 insert elIST; } 
 catch(DmlException e) { // DmlException handling code here. 
 System.debug('The following exception has occurred: ' + e.getMessage());
 }
 
 
        test.startTest();
           system.assertEquals(3, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);

            system.assertEquals(2, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(2, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
            
            //Delete some activities and run assertions again
            delete eList;
            system.assertEquals(3, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);
            system.assertEquals(1, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(1, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
           
          
            //Delete the rest activities and run assertions again for zero
            delete tList;
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
         
         
        }
 
}
}
Best Answer chosen by Ramanjot Sidhu
scottbcovertscottbcovert
Hi Ramanjot,

It looks like you are querying the ActivityHistories object in your helper class but in your test class you set the tasks' status to 'Not Started' and thus they would exist in the OpenActivities object for the account, contact, and opportunity records. I believe this may be the reason your test class is failing.

Also, when posting replies/questions there is a formatting option for inserting code so it will be easier for others to read and for referencing line numbers, etc.

Best,
Scott

All Answers

Shashi PatowaryShashi Patowary
Hi Ramanjot,

Why have you set (seeAllData = true) when you are not retrieving any data from org? Also can you please provide the trigger that you are trying to test?

Will be happy to help you.

Regards,
Shashi
scottbcovertscottbcovert
Hi Ramanjot,

It seems you might have removed some code for brevity's sake, but from what I see I can't tell where the Completed_Activities__c field's value is set for a new account and a value of 0 seems to make sense. Perhaps you are using some sort of workflow rule or trigger in your sandbox that doesn't exist in production to set this value?
Ramanjot SidhuRamanjot Sidhu
My Class:
public class ActivityUtils {
    
    //config
    
    String fieldToUpdate = 'Completed_Activities__c'; //this field must be added to each object we're updating
       
    //state
    set<id> accountIds;
    set<id> contactIds;
    set<id> opportunityIds;
  
    
    public ActivityUtils(sObject[] records) {
        accountIds = new set<id>();
        contactIds = new set<id>();
        opportunityIds = new set<id>();
        captureWhatAndWhoIds(records);
        addAccountIdsFromRlatedObjects();
    }
    
    public void updateAccountActivityCount() {
        if(accountIds.size() == 0) return;
                 updateActivityHistory('Account','WhatId', getStringFromIdSet(accountIds));
        
        
    }
    public void updateContactActivityCount() {
        if(contactIds.size() == 0) return;
               updateActivityHistory('Contact','WhoId', getStringFromIdSet(contactIds));

    }
    public void updateOpportunityActivityCount() {
        if(opportunityIds.size() == 0) return;
              updateActivityHistory('Opportunity','WhatId', getStringFromIdSet(opportunityIds));

    }
      
     
    private void updateActivityHistory(String objToUpdate, String queryFld, String updateIds) {
        string strQuery = 'SELECT Id, (SELECT Id FROM ActivityHistories Where ActivityDate >= THIS_FISCAL_YEAR ) FROM ' + objToUpdate + ' WHERE Id IN (' + updateIds + ')';        
System.debug(strQuery);
        sObject[] sobjects = new list<sobject>();
        for(sObject so : database.query(strQuery)) {
            ActivityHistory[] oActivities = so.getSObjects('ActivityHistories');
            Integer closedActivityCount = oActivities == null ? 0 : oActivities.size();
            sObject obj = createObject(objToUpdate, so.Id);
            obj.put(fieldToUpdate, closedActivityCount);
            sobjects.add(obj);
            system.debug('ActivityHistoryCount: ' + closedActivityCount);
        }
        update sobjects;
    }
    
    private void captureWhatAndWhoIds(sObject[] objects) {
        for(sObject o : objects) {
            Id whatId = (Id)o.get('WhatId');
            Id whoId = (Id)o.get('WhoId');
            if(whatId != null) {
                String objectName = getObjectNameFromId(whatId);
                if(objectName == 'account') accountIds.add(whatId);
                if(objectName == 'opportunity') opportunityIds.add(whatId);
            }
            if(whoId != null) {
                String objectName = getObjectNameFromId(whoId);
                if(objectName == 'contact') contactIds.add(whoId);
              }
        }
    }
    
    private void addAccountIdsFromRlatedObjects() {
        for(Opportunity o : [SELECT AccountId FROM Opportunity WHERE Id IN :opportunityIds]) accountIds.add(o.AccountId);
        for(Contact c : [SELECT AccountId FROM Contact WHERE Id IN :contactIds]) accountIds.add(c.AccountId);
    }
    
    private String getObjectNameFromId(Id objId) {
        String preFix = String.valueOf(objId).left(3).toLowercase();
        if(prefix == '001') return 'account';
        if(prefix == '003') return 'contact';
        if(prefix == '006') return 'opportunity';
         return '';
    }
    
    private String getStringFromIdSet(set<id> idSet) {
        string idString = '';
        for(Id i : idSet) idString+= '\'' + i + '\',';
        return idString == '' ? idString : idString.left(idString.length()-1); //If idString contains some ids we want to ensure we strip out the last comma
    }
    
    //The main part of the method below was taken from //Taken from http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dynamic_dml.htm
    //However we've modified this to accept an object id
    private sObject createObject(String typeName, Id objId) {
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName);
        if (targetType == null) {
            // throw an exception
        }
        
        // Instantiate an sObject with the type passed in as an argument
        //  at run time.
        return targetType.newSObject(objId);
    }
    
}



My Task Trigger:

trigger TaskTrigger on Task (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Completed Activity Count
    ActivityUtils au = new ActivityUtils(triggerRecords);
    au.updateAccountActivityCount();
    au.updateContactActivityCount();
    au.updateOpportunityActivityCount();
    
    
    }





My Event Trigger:

trigger EventTrigger on Event (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Open Activity Count
    ActivityUtils au = new ActivityUtils(triggerRecords);
    au.updateAccountActivityCount();
    au.updateContactActivityCount();
    au.updateOpportunityActivityCount();
 
}





 
Ramanjot SidhuRamanjot Sidhu
Note:  the two classes/triggers exit in my sandbox, and I have 85% code coverage. The triggers work well. However my testclass fails in my sandbox which is what is preventing me from deploying it to production.
 
scottbcovertscottbcovert
Hi Ramanjot,

It looks like you are querying the ActivityHistories object in your helper class but in your test class you set the tasks' status to 'Not Started' and thus they would exist in the OpenActivities object for the account, contact, and opportunity records. I believe this may be the reason your test class is failing.

Also, when posting replies/questions there is a formatting option for inserting code so it will be easier for others to read and for referencing line numbers, etc.

Best,
Scott
This was selected as the best answer
Ramanjot SidhuRamanjot Sidhu
@isTest(seeAllData = true)
private class test_ActivityUtils {
 
    static testMethod void mainTest() {
                Account acc = new Account();
                acc.Name = 'Test Account';
                acc.Industry = 'Transportation'; 
                insert acc;
 

        Contact c = new Contact();
        c.FirstName = 'Joe';
        c.LastName = 'Smith';
        c.AccountId = acc.Id;
        c.Email = 'ramanjot_sidhu@hotmail.com';
        insert c;


        Opportunity o = new Opportunity();
        o.AccountId = acc.Id;
        o.StageName = 'Open';
        o.Amount = 5000.00;
        o.CloseDate = Date.today() + 7;
        o.Name = 'Test Opp';
        insert o;
 

         
        Task[] tList = new list<task>(); 
        Event[] eList = new list<event>();
        for(Integer i=0; i<3; i++) {
            Task t = new Task();
            t.Status = 'Completed';
            t.Priority = 'Normal';
            t.Type = 'Call';
            t.ActivityDate = Date.Today() - 7;
            if(i==0) t.WhatId = acc.Id;
            if(i==1) t.WhatId = o.Id;
            if(i==2) t.WhoId = c.Id;
            tList.add(t);
 
          
         
          
            Event e = new Event();
            e.StartDateTime = Date.Today() - 20;
            e.EndDateTime = Date.Today() - 19;
            if(i==0) e.WhatId = acc.Id;
            if(i==1) e.WhatId = o.Id;
            if(i==2) e.WhoId = c.Id;
             eList.add(e);
        }
     
      insert tList;
      insert eList;
 
 
 
 
        test.startTest();
           system.assertEquals(6, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);
            system.assertEquals(2, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(2, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
            
            //Delete some activities and run assertions again
            delete eList;
            system.assertEquals(3, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);
            system.assertEquals(1, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(1, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
           
          
            //Delete the rest activities and run assertions again for zero
            delete tList;
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Account WHERE Id = :acc.Id].Completed_Activities__c);
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Opportunity WHERE Id = :o.Id].Completed_Activities__c);
            system.assertEquals(0, [SELECT Completed_Activities__c FROM Contact WHERE Id = :c.Id].Completed_Activities__c);
         
         
        }
 
}
scottbcovertscottbcovert
Hi Ramanjot,

I see that you updated your test class to set the activities to be completed, did that resolve your issue?
Ramanjot SidhuRamanjot Sidhu

I fixed my answer, and thanks for the advice everyone!. This code now works...anyone can use it to count completed activities :

I took the two codes online from the website:
http://rjpalombo.com/2013/11/counting-open-activities-salesforce/
http://mysalesforcestuff.blogspot.ca/2015/04/counting-open-and-closed-activities-in.html

(I AM NOT TAKING CREDIT FOR THIS)

Tweeked the codes alittle bit ....added a field called 'Completed Activities' for following objectsl Accounts, Contacts, and Opportunities

Below is all the information you need:

1) Class
 

public class ActivityUtils {
    
    //config
    
    String fieldToUpdate = 'Completed_Activities__c'; //this field must be added to each object we're updating
       
    //state
    set<id> accountIds;
    set<id> contactIds;
    set<id> opportunityIds;
  
    
    public ActivityUtils(sObject[] records) {
        accountIds = new set<id>();
        contactIds = new set<id>();
        opportunityIds = new set<id>();
        captureWhatAndWhoIds(records);
        addAccountIdsFromRlatedObjects();
    }
    
    public void updateAccountActivityCount() {
        if(accountIds.size() == 0) return;
                 updateActivityHistory('Account','WhatId', getStringFromIdSet(accountIds));
        
        
    }
    public void updateContactActivityCount() {
        if(contactIds.size() == 0) return;
               updateActivityHistory('Contact','WhoId', getStringFromIdSet(contactIds));

    }
    public void updateOpportunityActivityCount() {
        if(opportunityIds.size() == 0) return;
              updateActivityHistory('Opportunity','WhatId', getStringFromIdSet(opportunityIds));

    }
      
     
    private void updateActivityHistory(String objToUpdate, String queryFld, String updateIds) {
        string strQuery = 'SELECT Id, (SELECT Id FROM ActivityHistories Where ActivityDate >= THIS_FISCAL_YEAR ) FROM ' + objToUpdate + ' WHERE Id IN (' + updateIds + ')';        
System.debug(strQuery);
        sObject[] sobjects = new list<sobject>();
        for(sObject so : database.query(strQuery)) {
            ActivityHistory[] oActivities = so.getSObjects('ActivityHistories');
            Integer closedActivityCount = oActivities == null ? 0 : oActivities.size();
            sObject obj = createObject(objToUpdate, so.Id);
            obj.put(fieldToUpdate, closedActivityCount);
            sobjects.add(obj);
            system.debug('ActivityHistoryCount: ' + closedActivityCount);
        }
        update sobjects;
    }
    
    private void captureWhatAndWhoIds(sObject[] objects) {
        for(sObject o : objects) {
            Id whatId = (Id)o.get('WhatId');
            Id whoId = (Id)o.get('WhoId');
            if(whatId != null) {
                String objectName = getObjectNameFromId(whatId);
                if(objectName == 'account') accountIds.add(whatId);
                if(objectName == 'opportunity') opportunityIds.add(whatId);
            }
            if(whoId != null) {
                String objectName = getObjectNameFromId(whoId);
                if(objectName == 'contact') contactIds.add(whoId);
              }
        }
    }
    
    private void addAccountIdsFromRlatedObjects() {
        for(Opportunity o : [SELECT AccountId FROM Opportunity WHERE Id IN :opportunityIds]) accountIds.add(o.AccountId);
        for(Contact c : [SELECT AccountId FROM Contact WHERE Id IN :contactIds]) accountIds.add(c.AccountId);
    }
    
    private String getObjectNameFromId(Id objId) {
        String preFix = String.valueOf(objId).left(3).toLowercase();
        if(prefix == '001') return 'account';
        if(prefix == '003') return 'contact';
        if(prefix == '006') return 'opportunity';
         return '';
    }
    
    private String getStringFromIdSet(set<id> idSet) {
        string idString = '';
        for(Id i : idSet) idString+= '\'' + i + '\',';
        return idString == '' ? idString : idString.left(idString.length()-1); //If idString contains some ids we want to ensure we strip out the last comma
    }
    
    //The main part of the method below was taken from //Taken from http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dynamic_dml.htm
    //However we've modified this to accept an object id
    private sObject createObject(String typeName, Id objId) {
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName);
        if (targetType == null) {
            // throw an exception
        }
        
        // Instantiate an sObject with the type passed in as an argument
        //  at run time.
        return targetType.newSObject(objId);
    }
    
}
 


Task Trigger:
trigger TaskTrigger on Task (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Completed Activity Count
    ActivityUtils au = new ActivityUtils(triggerRecords);
    au.updateAccountActivityCount();
    au.updateContactActivityCount();
    au.updateOpportunityActivityCount();
    
    
    }


Event Trigger
trigger EventTrigger on Event (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Open Activity Count
    ActivityUtils au = new ActivityUtils(triggerRecords);
    au.updateAccountActivityCount();
    au.updateContactActivityCount();
    au.updateOpportunityActivityCount();
 
}


TestClass - you can find above this post
 

Ramanjot SidhuRamanjot Sidhu
Hi Scott, not entirely, that step was part of the process. I had certain values for the task fields that did not exit in my salesforce. Also The Date.Time (Now) was causing an issue, and I changed that to Date.Today(). These two changes made a big different.