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
Jan Kopejtko 1Jan Kopejtko 1 

Test class for my trigger help

Hi, I found a great trigger that would help me with my thing - it populates my Number_of_Contacts__c field on accounts with the amount of the contacts related to the account.

But now I don't know how to write test class for this trigger. I wrote test classes for triggers before, but this one is too difficult for me at the moment. Can you write the test for me please



/* Provide summary of Number of Contacts on Account record */

trigger ContactSumTrigger on Contact (after delete, after insert, after undelete,
after update) {

    Contact[] cons;
    if (Trigger.isDelete)
        cons = Trigger.old;
    else
        cons = Trigger.new;
    
    // get list of accounts
    Set<ID> acctIds = new Set<ID>();
    for (Contact con : cons) {
            acctIds.add(con.AccountId);
    }

    Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([select Id
                                                            ,AccountId
                                                            from Contact
                                                            where AccountId in :acctIds]);

    Map<ID, Account> acctsToUpdate = new Map<ID, Account>([select Id
                                                                 ,Number_of_Contacts__c
                                                                  from Account
                                                                  where Id in :acctIds]);
                                                                
    for (Account acct : acctsToUpdate.values()) {
        Set<ID> conIds = new Set<ID>();
        for (Contact con : contactsForAccounts.values()) {
            if (con.AccountId == acct.Id)
                conIds.add(con.Id);
        }
        if (acct.Number_of_Contacts__c != conIds.size())
            acct.Number_of_Contacts__c = conIds.size();
    }

    update acctsToUpdate.values();

}
Boss CoffeeBoss Coffee
There are a few changes I'd make to the trigger itself, but I'll provide the test class as it is. The setup of test records may be different depending on what required fields you have on those objects. The two test methods just covers insert and delete, which is 100% code coverage, but ideally you'd test for undelete and update cases as well. This should give you a good start if you want to test those scenarios as well.
// Test class for ContactSumTrigger
// Ensures Account updates correctly when changes to related Contacts are made
@isTest
public class ContactSumTriggerTest {

    // Set up the records to be tested
    @testSetup
    static void createRecords() {
        // Set up five Accounts
        List<Account> accounts = new List<Account>();
        for(Integer i = 0; i < 5; i++) {
            accounts.add(new Account(
                Name='testAccount' + i
            ));
        }
        insert accounts;
        
        // Set up five Contacts for each Account
        List<Contact> contacts = new List<Contact>();
        for(Account acc : accounts) {
            for(Integer i = 0; i < 5; i++) {
                contacts.add(new Contact(
                    LastName='testContact' + i,
                    AccountId=acc.Id
                ));
            }
        }
        insert contacts;
    }

    // Test the insertion of Contacts
    @isTest
    public static void testContactInsert() {
        
        test.startTest();
        // Set one additional Contact for each Account
        List<Account> accounts = [SELECT Id FROM Account];
        List<Contact> contacts = new List<Contact>();
        for(Account acc : accounts) {
            contacts.add(new Contact(
                LastName='testContactInsert',
                AccountId=acc.Id
            ));
        }
        insert contacts;
        test.stopTest();
        
        // Make sure there are the five existing accounts
        List<Account> accList = [SELECT Id, Number_of_Contacts__c FROM Account];
        System.assertEquals(5, accList.size());
        
        // For each account, make sure the field was updated to reflect the number of related contacts
        for(Account acc : [SELECT Id, Number_of_Contacts__c FROM Account]) {
            System.assertEquals(6, acc.Number_of_Contacts__c);
        }
    }
    
    // Test the deletion of Contacts
    @isTest
    public static void testContactDelete() {
        
        test.startTest();
        // Delete one contact from each Account
        List<Account> accounts = [SELECT Id, (SELECT Id FROM Contacts) FROM Account];
        List<Contact> contacts = new List<Contact>();
        for(Account acc : accounts) {
            if(acc.Contacts.size() > 0) {
                contacts.add(acc.Contacts[0]);
            }
        }
        delete contacts;
        test.stopTest();
        
        // Make sure there are the five existing accounts
        List<Account> accList = [SELECT Id, Number_of_Contacts__c FROM Account];
        System.assertEquals(5, accList.size());
        
        // For each account, make sure the field was updated to reflect the number of related contacts
        for(Account acc : [SELECT Id, Number_of_Contacts__c FROM Account]) {
            System.assertEquals(4, acc.Number_of_Contacts__c);
        }
    }
}
Let me know if you need any more help, cheers!
Jan Kopejtko 1Jan Kopejtko 1
@Boss Coffee Honestly that is very impressive. The tests passed! How can I repay you my friend?
Boss CoffeeBoss Coffee
Glad to hear! If you'd like, mark the post as the answer and update the thread to solved.
Jan Kopejtko 1Jan Kopejtko 1
@Boss Coffee Hey umm just another question: What if there is a custom lookup field called "CLookup" on Contact with a filter on account Record Type="Type1" and I want to change the testing class so that it passes. I changes the field in it according to the lookup field, that's fine, but when adding the accounts, I need to specify RecordType. You helped me with specifying Name in a cool way (Name="test account" + i), but I can not refer to RecordType or RecordTypeId - it throws me an arrow saying the field does not exist. Can you explain to me why this happens, because I have the field on Account (RecordTypeId), yet it can not be refered to.
Cheers