Use Case:
Write a trigger:
Count the total number of contacts associated to an Account whenever a Contact is,
- Inserted, Updated or Deleted related to the Account.
- Field Total_Contacts_Count__c should get updated with the latest count.
Pre-requisite: Create a Number field with API name “Total_Contacts_Count__c” on Account.
trigger ContactTrigger on Contact (after insert, after update, after delete) {if(Trigger.isAfter) {// Code runs when any contact is inserted.if(Trigger.isInsert) {// Map of Account Ids as the Keys and count of contacts which need to be updated later as the value.Map<Id, Integer> accMapWithContsCount = new Map<Id, Integer>();// Check if the inserted contact has some value in the account for each contact,// if yes then add the Integer 1 in the mapfor(Contact con : Trigger.new) {// it would check if the key 'AccountId' already exists in the map, if no then simply set the integer value 1 for the account.// else update the value to 1.if(!accMapWithContsCount.containsKey(con.AccountId)) {accMapWithContsCount.put(con.AccountId, 1);}else {accMapWithContsCount.put(con.AccountId, accMapWithContsCount.get(con.AccountId) + 1);}}// Get all the accounts with the keySet of map and update field 'Total_Contacts_Count__c' with the values from the map.List<Account> accountsToBeUpdated = [Select Id, Total_Contacts_Count__c From Account Where Id IN :accMapWithContsCount.keySet()];for(Account acc : accountsToBeUpdated) {acc.Total_Contacts_Count__c = acc.Total_Contacts_Count__c + accMapWithContsCount.get(acc.Id);}update accountsToBeUpdated;}// Code runs when any contact is updated.if(Trigger.isUpdate) {Map<Id, Integer> accMapWithContsCount = new Map<Id, Integer>();for(Contact con : Trigger.new) {// Condition which checks that the code should run only if there is a change in Account field of contact.if(con.AccountId != Trigger.oldMap.get(con.Id).AccountId) {// Check when previously there was nothing in the account field but then some account was populated during updation.if(Trigger.oldMap.get(con.Id).AccountId == null) {if(!accMapWithContsCount.containsKey(con.AccountId)) {accMapWithContsCount.put(con.AccountId, 1);}else {accMapWithContsCount.put(con.AccountId, accMapWithContsCount.get(con.AccountId) + 1);}}// Check when previously there was some value in the Account field but during updation the account was removed// and new value is nullelse if(Trigger.oldMap.get(con.Id).AccountId != null && con.AccountId == null) {if(!accMapWithContsCount.containsKey(Trigger.oldMap.get(con.Id).AccountId)) {// since there is no value after updation in the field Account of Contact// so new Total Contacts Count on Account would be lessaccMapWithContsCount.put(Trigger.oldMap.get(con.Id).AccountId, -1);}else {accMapWithContsCount.put(Trigger.oldMap.get(con.Id).AccountId, accMapWithContsCount.get(Trigger.oldMap.get(con.Id).AccountId) - 1);}}// Check when account associated to contact before and after updation was different.else {// For new account which was populated to the contactif(!accMapWithContsCount.containsKey(con.AccountId)) {accMapWithContsCount.put(con.AccountId, 1);}else {accMapWithContsCount.put(con.AccountId, accMapWithContsCount.get(con.AccountId) + 1);}// For old account which was updated with the new oneId oldId = Trigger.oldMap.get(con.Id).AccountId;if(!accMapWithContsCount.containsKey(oldId)) {accMapWithContsCount.put(oldId, -1);}else {accMapWithContsCount.put(oldId, accMapWithContsCount.get(oldId) - 1);}}}}// Get all the accounts with the keySet of map and update field 'Total_Contacts_Count__c' with the values from the map.List<Account> accountsToBeUpdated = [Select Id, Total_Contacts_Count__c From Account Where Id IN :accMapWithContsCount.keySet()];for(Account acc : accountsToBeUpdated) {acc.Total_Contacts_Count__c = acc.Total_Contacts_Count__c + accMapWithContsCount.get(acc.Id);}update accountsToBeUpdated;}// Code runs when any contact is deleted.if(Trigger.isDelete) {Map<Id, Integer> accMapWithContsCount = new Map<Id, Integer>();for(Contact con : Trigger.old) {if(!accMapWithContsCount.containsKey(con.AccountId)) {accMapWithContsCount.put(con.AccountId, -1);}else {accMapWithContsCount.put(con.AccountId, accMapWithContsCount.get(con.AccountId) - 1);}}// Get all the accounts with the keySet of map and update field 'Total_Contacts_Count__c' with the values from the map.List<Account> accountsToBeUpdated = [Select Id, Total_Contacts_Count__c From Account Where Id IN :accMapWithContsCount.keySet()];for(Account acc : accountsToBeUpdated) {acc.Total_Contacts_Count__c = acc.Total_Contacts_Count__c + accMapWithContsCount.get(acc.Id);}update accountsToBeUpdated;}}}
Test Class:
Scenario 1- Test the scenario which checks that whenever a new Contact is inserted to some account, Total_Contacts_Count__c field should be updated to value 1.
Scenario 2- Test the scenario when Account field on a Contact is updated from null to some value.
Scenario 3- Test the scenario when Account field on a Contact is updated from some value to null.
Scenario 4- Test the scenario when Account field on a Contact is updated from some value to another value.
Scenario 5- Test the scenario when a contact record is deleted. Update related account’s field ‘Total_Contacts_Count__c’.
@isTestprivate class ContactTriggerTest {@testSetupstatic void dataSetup() {Account newAcc = new Account(Name='TestAccount1');insert newAcc;Account newAcc2 = new Account(Name='TestAccount2');insert newAcc2;}// Test the scenario which checks that when we insert a new Contact to some account,// Total_Contacts_Count__c field should be updated to value 1.// Here, we inserted 2 contacts, Total_Contacts_Count__c should be updated to 2.@isTeststatic void test_afterInsert() {Account insertedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Name = 'TestAccount1'];System.assertEquals(0, insertedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');List<Contact> contacts = new List<Contact>();for(Integer i=0; i<2; i++) {contacts.add(new Contact(LastName='TestContact'+i, AccountId=insertedAcc1.Id));}Test.startTest();insert contacts;Account udpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(2, udpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');Test.stopTest();}// Test the scenario when Account field on a Contact is updated from null to some value@isTeststatic void test_afterUpdate_scenario1() {// Verify that Total_Contacts_Count__c value is 0 initiallyAccount insertedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Name = 'TestAccount1'];System.assertEquals(0, insertedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');// Verify that Total_Contacts_Count__c value is 0 after the insertion of the contactList<Contact> contacts = new List<Contact>();for(Integer i=0; i<2; i++) {contacts.add(new Contact(LastName='TestContact'+i));}insert contacts;Account udpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(0, udpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');// Verify that Total_Contacts_Count__c value is 1 after contact is updated with the accountTest.startTest();for(Contact con: contacts) {con.AccountId = insertedAcc1.Id;}update contacts;Test.stopTest();Account newUdpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(2, newUdpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');}// Test the scenario when Account field on a Contact is updated from some value to null@isTeststatic void test_afterUpdate_scenario2() {Account insertedAcc1 = [Select Id From Account Where Name = 'TestAccount1'];List<Contact> contacts = new List<Contact>();for(Integer i=0; i<2; i++) {contacts.add(new Contact(LastName='TestContact'+i, AccountId=insertedAcc1.Id));}insert contacts;Account udpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(2, udpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');Test.startTest();for(Contact con : contacts) {con.AccountId = null;}update contacts;Test.stopTest();Account newUdpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(0, newUdpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');}// Test the scenario when Account field on a Contact is updated from some value to another value@isTeststatic void test_afterUpdate_scenario3() {Account insertedAcc1 = [Select Id From Account Where Name = 'TestAccount1'];Account insertedAcc2 = [Select Id From Account Where Name = 'TestAccount2'];List<Contact> contacts = new List<Contact>();for(Integer i=0; i<2; i++) {contacts.add(new Contact(LastName='TestContact'+i, AccountId=insertedAcc1.Id));}insert contacts;Account udpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];Account udpatedAcc2 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc2.Id];System.assertEquals(2, udpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');System.assertEquals(0, udpatedAcc2.Total_Contacts_Count__c, 'Contacts count does not match.');Test.startTest();for(Contact con : contacts) {con.AccountId = udpatedAcc2.Id;}update contacts;Test.stopTest();Account newUdpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];Account newUdpatedAcc2 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc2.Id];System.assertEquals(0, newUdpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');System.assertEquals(2, newUdpatedAcc2.Total_Contacts_Count__c, 'Contacts count does not match.');}// Test the scenario when a contact is deleted.// Update related account's field 'Total_Contacts_Count__c'@isTeststatic void test_afterDelete() {Account insertedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Name = 'TestAccount1'];System.assertEquals(0, insertedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');List<Contact> contacts = new List<Contact>();for(Integer i=0; i<2; i++) {contacts.add(new Contact(LastName='TestContact'+i, AccountId=insertedAcc1.Id));}insert contacts;Account udpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(2, udpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');Test.startTest();delete contacts;Test.stopTest();Account newUdpatedAcc1 = [Select Id, Total_Contacts_Count__c From Account Where Id = :insertedAcc1.Id];System.assertEquals(0, newUdpatedAcc1.Total_Contacts_Count__c, 'Contacts count does not match.');}}
Code Coverage: 100%
Mr.apex Ace i think your code is not satisfying all the conditions
Short and Simple
trigger ContactTrigger on Contact (after insert,after update, after delete){
Set accountIds = new Set();
if(Trigger.isInsert || Trigger.isUpdate){
for(Contact con : Trigger.new){
accountIds.add(con.AccountId);
}
}
if(Trigger.isDelete){
for(Contact con : Trigger.old){
accountIds.add(con.AccountId);
}
}
List accList = [SELECT Id,Total_Contacts_Count__c,(SELECT id FROM Contacts)
FROM Account WHERE Id IN: accountIds];
for(Account acc : accList){
acc.Total_Contacts_Count__c = acc.Contacts.Size();
}
update accList;
}
Hey, It’s not passing all test cases as you forgot 2 cases of after update , I tried including those and it is passing all test cases.
trigger ContactTrigger on Contact (after insert, after update , after delete){
ContactTriggerHandler.countAllContactOfAccount(trigger.new,trigger.old,trigger.oldMap);
}
public static void countAllContactOfAccount(List newContacts,List oldContacts,MapoldMap){
if(trigger.isAfter){
List accounts = new List();
if(trigger.isInsert){
Set accIds = new Set();
for(Contact con: newContacts){
if(con.AccountId != null)
accIds.add(con.AccountId);
}
accounts = updateAccounts(accIds);
}
if(trigger.isUpdate){
system.debug(‘hi’);
Set accIds = new Set();
for(Contact con: newContacts){
if(oldMap.get(con.Id).AccountId != con.AccountId){
if(con.AccountId == null){
accIds.add(oldMap.get(con.Id).AccountId);
}else if(con.AccountId != null && oldMap.get(con.Id).AccountId == null){
accIds.add(con.AccountId);
}else {
accIds.add(oldMap.get(con.Id).AccountId);
system.debug(‘hi’);
accIds.add(con.AccountId);
system.debug(‘hi’);
}
}
accounts = updateAccounts(accIds);
}
}
if(trigger.isDelete){
Set accIds = new Set();
for(Contact con: oldContacts){
if(con.AccountId != null)
accIds.add(con.AccountId);
}
accounts = updateAccounts(accIds);
}
update accounts;
}
}
private static List updateAccounts(Set accIds){
List accounts = [Select id, (Select id from Contacts) from Account where id in : accIds];
for(Account acc: accounts){
acc.Total_Contacts_Count__c = acc.Contacts.size();
}
return accounts;
}