+ Start a Discussion
Michael Christie 13Michael Christie 13 

Need to Deactivate Trigger with Low Code Coverage

Hello,

There is an old trigger in our org that needs to be deactivated. However, the trigger's test class only has 65% code coverage. I did not write this code and do not have a background in development. Could anyone offer clear edits to make so that I can successfully deploy the deactivated trigger to production?

Trigger:
trigger AccountTrigger on Account (before delete, before insert, before update,after insert) {
    AccountTriggerHandler.execute(Trigger.new, Trigger.newMap, Trigger.old, Trigger.oldMap, 
                          Trigger.isInsert, Trigger.isUpdate, Trigger.isDelete, Trigger.isBefore, Trigger.isAfter);
    AccountTriggerHandler.executeLeadLink(Trigger.new,Trigger.old,Trigger.isUpdate,Trigger.isBefore,Trigger.isInsert,Trigger.isAfter);
}
The Class referenced in the trigger:
public with sharing class AccountTriggerHandler {
	
	static RecordType applicantRecordType;
	static Profile adminProfile;
	static {
		applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
		adminProfile = [Select Id, Name From Profile Where Name = 'System Administrator'];
	}
	
	public static void execute(List<Account> newList, Map<Id, Account> newMap,
                               List<Account> oldList, Map<Id, Account> oldMap,
                               Boolean isInsert, Boolean isUpdate, Boolean isDelete, Boolean isBefore, Boolean isAfter) {    
    	List<Account> accList = new List<Account>();
    	if (isDelete) {
    		for (Account acc : oldList)
    			accList.add(acc);
    	}
    	else {
    		for (Account acc : newList)
    			accList.add(acc);
    	}    	
    	for (Account acc : accList)	{
    		if (isBefore) {
	    		if (acc.RecordTypeId == applicantRecordType.Id && 
	    			System.Userinfo.getProfileId() != adminProfile.Id) {	    		
	    			acc.addError('Only System Administrators may create, edit, or delete Applicants');		
	    		}
    		}
    	}		                           	
    }
    
	public static Map<String,Lead> GetLeadsWithAccountEmailAddress(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountEmails=new Set<String>();
        for(Account a:accounts){
			accountEmails.add(a.PersonEmail.toLowerCase());
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Email in:accountEmails];   		
        for(Lead lead:leads){
           mappedLeads.put(lead.Email.toLowerCase(),lead);
        }
        return mappedLeads;
    }

	public static Map<String,Lead> GetLeadsWithAccountExternalReference(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountExternalRef=new Set<String>();
        for(Account a:accounts){
            if (!String.isBlank(a.ExternalReference__c)){
                accountExternalRef.add(a.ExternalReference__c);
            }			
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:accountExternalRef];   	
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }
        return mappedLeads;
    }    
    
    public static Map<String,Lead> GetLeadsWithAccountRelation(List<Account> accounts){
		Set<Id> leadIds=new Set<Id>();
        Map<String,Lead> mappedLeads=new Map<String,Lead>();   
        for(Account acc:accounts){
            leadIds.add(acc.Related_Lead__c);
        }        
		List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:leadIds];	
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }   
        return mappedLeads;
    }
    
	public static void CreateLeadLinkAndUpdateLeadData(List<Account> newList,Boolean updateAccount){
        Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
        Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);
        
        if (mappedLeads.size()==0 &&  mappedLeadsByExternalReference.size()==0){
            return;
        }        
        List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:newList){   
            //Check the external ref first
            Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
            if (lead==null){
                lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
            } 
            if (lead!=null){ 
                if (updateAccount && lead.Account__c==null){
                    acc.Related_Lead__c=lead.id;
                }                
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }
        if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }
    } 
	
    public static void UpdateLeadData(List<Account> accList){
        Map<String,Lead> mappedLeads=GetLeadsWithAccountRelation(accList);
        
		List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:accList){   
            Lead lead=mappedLeads.get(acc.Related_Lead__c);
            if (lead!=null){           
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }  
		if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }        
    }
    
	public static void executeLeadLink(List<Account> newList, List<Account> oldList,Boolean isUpdate,Boolean isBefore,Boolean isInsert,Boolean isAfter){      
        if(isInsert && isBefore){     
            Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
            Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);      
            for(Account acc:newList){                
                Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
                if (lead==null){
                    lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
                }  
                //Check if lead is not null and lead does not have an account already associated with it
                if (lead!=null && lead.Account__c==null){
                    acc.Related_Lead__c=lead.Id;
                }
                acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);
            }
        } 
        if (isInsert && isAfter){           
            CreateLeadLinkAndUpdateLeadData(newList,false);
        }        
        if (isBefore && isUpdate){
			List<Account> accWithNoLeads=new List<Account>();
			List<Account> accWithLeads=new List<Account>();			
		    for(Account acc:newList)
		 	{
		       	acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);		       
				if (acc.Related_Lead__c==null){
					accWithNoLeads.add(acc);						
		       	}
		       	else{
		       		accWithLeads.add(acc);
		       	}
		 	}
         	
         	//Send the accounts that do not have leads - we need to search if leads exists and then link the lead
			CreateLeadLinkAndUpdateLeadData(accWithNoLeads,true);	
            
            //If the account already has a lead, just update the lead no need to relink the accounts
            UpdateLeadData(accWithLeads);
        }
    }    
}

Test Class:
@isTest
private class Test_AccountTriggerHandler {

	static RecordType applicantRecordType;
	
	static {
		applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
	}

    static testMethod void testAccountError() {
        test.startTest();
        
        Account acc = CreateTestData.createAccount('U_testAccount@tntp.org','externalRef');              
        acc.FirstName = 'Test Account3';
        update acc;
        delete acc;
        test.stopTest();
    }
    
    static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test2@tntp.org'); 
        String externalRef=String.valueOf(lead.Id);
		
        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org',externalRef); 
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];			

        test.stopTest();
    }    
    
	static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_Email() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with same email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id,Account__c From Lead l Where l.Email ='U_test1@tntp.org'];	
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];			
        
        test.stopTest();
    }    
    
    static testMethod void Account_Doesnot_Get_Linked_To_Lead_Because_Of_Missing_Account_ExternalReference() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test2@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id From Lead l Where l.Email ='U_test1@tntp.org'];	
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test2@tntp.org'];			
		
        //Should find no match
        System.assertEquals(accounts[0].Related_Lead__c, null);
        
        test.stopTest();
    } 
}

Thank you in advance for any assistance you can provide. 
 
Best Answer chosen by Michael Christie 13
Christan G 4Christan G 4
Hi Michael, thank you again for understanding. I started reviewing the "Overall Code Coverage" section in your screenshots and realized something. The overall test coverage for that one trigger class is 96% which is more than enough coverage to migrate this to Production. If you are still getting an error stating that there is less than 75% code coverage when trying to deploy to Production, then this indicates that there is another class which is bringing the overall test coverage down.

In order to deploy to Production, the overall test code coverage needs to be above 75% and none of the Apex test class could fail. We fixed half of the problem by addressing all those exception errors. Now we have to figure out what other code needs additional test code coverage to bring the overall percentage above 75%.

If it is more convenient for you, I can provide you my email and schedule a Zoom meeting to further troubleshoot this together. I know we've been chatting back and forth for awhile so I just wanted to give you this option if you want a quicker fix.

Thanks again for understanding and I look forward to hearing back from you soon!

All Answers

ANUTEJANUTEJ (Salesforce Developers) 
Hi Michael,

In case you would like to deactivate the trigger you simply need to navigate to the trigger click on edit and then uncheck the active check box then the trigger will be deactivated on doing this.

I hope this helps and in case if this comes useful can you please choose this as best answer so that it can be used by others in the future.

Regards,
Anutej
Michael Christie 13Michael Christie 13
Anutej,

There is no option to deactivate a trigger in production (by navigating to Setup --> Custom Code --> Apex Triggers). The option exists in sandboxes. However, I am unable to deploy the trigger and its classes from the sandbox to production because code coverage is below 75%. I know there are other methods besides deploying a change set, but simply deactivating a trigger in production is not possible. https://help.salesforce.com/articleView?id=000327373&language=en_US&type=1&mode=1 (https://help.salesforce.com/articleView?id=000327373&language=en_US&type=1&mode=1
ANUTEJANUTEJ (Salesforce Developers) 
To my knowledge, I think you need to have only 1% code coverage for triggers if that is the case I think you certainly would be able to deactivate using the methods mentioned in the above link you stated.
Michael Christie 13Michael Christie 13
I am trying to deploy the deactivated trigger and its classes to production, but am unable to because the deployment only has 65% code coverage and not 75%. I would like help in increasing the coverage. 
Christan G 4Christan G 4
Hi Michael, I hope you are well. When possible, can you provide a screenshot of the lines of code that are marked in red when you run the test class? It'll provide insight as to which lines of code needs test coverage. 
Michael Christie 13Michael Christie 13
Hi Christan,

Yes, absolutely. It looks like lines 55 and 34:

Screenshot

Class Name: Test_AccountTriggerHandler
Method Name:  Account_Gets_Linked_To_Lead_Based_On_Account_Email
Error Message: System.AssertException: Assertion Failed: Expected: null, Actual: 00Q1Y00001xUtI9UAK
Stack Trace: Class.Test_AccountTriggerHandler.Account_Gets_Linked_To_Lead_Based_On_Account_Email: line 55, column 1

Class Name: Test_AccountTriggerHandler
Method Name: Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails
Error Message: System.AssertException: Assertion Failed: Expected: null, Actual: 00Q1Y00001xUtIAUA0 Stack Trace: Class.Test_AccountTriggerHandler.Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails: line 34, column 1
Christan G 4Christan G 4
Thank You Michael for posting the error messages! Something is not adding up after review the error messages with the test code you posted for "Test_AccountTriggerHandler". System.AssertExceptions are usually thrown when a System.assert() method within a test class fails. As you mentioned, it states that code lines 34 and 55 are throwing errors but when I reviewed the test code, I see no System.assert() methods in either of those lines. The only System.assert() method that I saw was in code line 70. Thus, this is making me believe that the test class at some point was altered. Production, possibly, may have an older version of this test class which has these System.assert() methods that are causing errors. If possible, can you copy and paste the test method codes for both the methods that are given an error here? Please ensure that within their code block, there exist a System.assert method within them.
Michael Christie 13Michael Christie 13
Hi Christan,

That's a great point - the sandbox I copied that from hadn't been refreshed in a while. Here is the full "AccountTriggerHandler" code from our Production instance: 
 
public with sharing class AccountTriggerHandler {
  
  static RecordType applicantRecordType;
  static Profile adminProfile;
  static {
    applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
    adminProfile = [Select Id, Name From Profile Where Name = 'System Administrator'];
  }
  
  public static void execute(List<Account> newList, Map<Id, Account> newMap,
                               List<Account> oldList, Map<Id, Account> oldMap,
                               Boolean isInsert, Boolean isUpdate, Boolean isDelete, Boolean isBefore, Boolean isAfter) {    
      List<Account> accList = new List<Account>();
      if (isDelete) {
        for (Account acc : oldList)
          accList.add(acc);
      }
      else {
        for (Account acc : newList)
          accList.add(acc);
      }      
      for (Account acc : accList)  {
        if (isBefore) {
          if (acc.RecordTypeId == applicantRecordType.Id && 
            System.Userinfo.getProfileId() != adminProfile.Id) {          
            acc.addError('Only System Administrators may create, edit, or delete Applicants');    
          }
        }
      }                                 
    }
    
  public static Map<String,Lead> GetLeadsWithAccountEmailAddress(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountEmails=new Set<String>();
        for(Account a:accounts){
      accountEmails.add(a.PersonEmail.toLowerCase());
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Email in:accountEmails];       
        for(Lead lead:leads){
           mappedLeads.put(lead.Email.toLowerCase(),lead);
        }
        return mappedLeads;
    }

  public static Map<String,Lead> GetLeadsWithAccountExternalReference(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountExternalRef=new Set<String>();
        for(Account a:accounts){
            if (!String.isBlank(a.ExternalReference__c)){
                accountExternalRef.add(a.ExternalReference__c);
            }      
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:accountExternalRef];     
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }
        return mappedLeads;
    }    
    
    public static Map<String,Lead> GetLeadsWithAccountRelation(List<Account> accounts){
    Set<Id> leadIds=new Set<Id>();
        Map<String,Lead> mappedLeads=new Map<String,Lead>();   
        for(Account acc:accounts){
            leadIds.add(acc.Related_Lead__c);
        }        
    List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:leadIds];  
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }   
        return mappedLeads;
    }
    
  public static void CreateLeadLinkAndUpdateLeadData(List<Account> newList,Boolean updateAccount){
        Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
        Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);
        
        if (mappedLeads.size()==0 &&  mappedLeadsByExternalReference.size()==0){
            return;
        }        
        List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:newList){   
            //Check the external ref first
            Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
            if (lead==null){
                lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
            } 
            if (lead!=null){ 
                if (updateAccount && lead.Account__c==null){
                    acc.Related_Lead__c=lead.id;
                }                
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }
        if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }
    } 
  
    public static void UpdateLeadData(List<Account> accList){
        Map<String,Lead> mappedLeads=GetLeadsWithAccountRelation(accList);
        
    List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:accList){   
            Lead lead=mappedLeads.get(acc.Related_Lead__c);
            if (lead!=null){           
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }  
    if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }        
    }
    
  public static void executeLeadLink(List<Account> newList, List<Account> oldList,Boolean isUpdate,Boolean isBefore,Boolean isInsert,Boolean isAfter){      
        if(isInsert && isBefore){     
            Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
            Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);      
            for(Account acc:newList){                
                Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
                if (lead==null){
                    lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
                }  
                //Check if lead is not null and lead does not have an account already associated with it
                if (lead!=null && lead.Account__c==null){
                    acc.Related_Lead__c=lead.Id;
                }
                acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);
            }
        } 
        if (isInsert && isAfter){           
            CreateLeadLinkAndUpdateLeadData(newList,false);
        }        
        if (isBefore && isUpdate){
      List<Account> accWithNoLeads=new List<Account>();
      List<Account> accWithLeads=new List<Account>();      
        for(Account acc:newList)
       {
             acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);           
        if (acc.Related_Lead__c==null){
          accWithNoLeads.add(acc);            
             }
             else{
               accWithLeads.add(acc);
             }
       }
           
           //Send the accounts that do not have leads - we need to search if leads exists and then link the lead
      CreateLeadLinkAndUpdateLeadData(accWithNoLeads,true);  
            
            //If the account already has a lead, just update the lead no need to relink the accounts
            UpdateLeadData(accWithLeads);
        }
    }    
}

 
Christan G 4Christan G 4
Thanks Michael! When possible, can you also post the test class code as well since that is the root of the problem? Thanks in advance!
Michael Christie 13Michael Christie 13
Thank you for the quick reply, Christan! Yes, here it is:
 
@isTest
private class Test_AccountTriggerHandler {

  static RecordType applicantRecordType;
  
  static {
    applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
  }

    static testMethod void testAccountError() {
        test.startTest();
        
        Account acc = CreateTestData.createAccount('U_testAccount@tntp.org','externalRef');              
        acc.FirstName = 'Test Account3';
        update acc;
        delete acc;
        test.stopTest();
    }
    
    static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test2@tntp.org'); 
        String externalRef=String.valueOf(lead.Id);
    
        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org',externalRef); 
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];      
        
        //Account object should have correct LeadId
        System.assertEquals(accounts[0].Related_Lead__c, externalRef);

        test.stopTest();
    }    
    
  static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_Email() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with same email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id,Account__c From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];      
    
        //Account object should have correct LeadId
        System.assertEquals(accounts[0].Related_Lead__c, leads[0].Id);
        
        //Lead object should have correct AccountId
        System.assertEquals(leads[0].Account__c, accounts[0].Id);
        
        test.stopTest();
    }    
    
    static testMethod void Account_Doesnot_Get_Linked_To_Lead_Because_Of_Missing_Account_ExternalReference() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test2@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test2@tntp.org'];      
    
        //Should find no match
        System.assertEquals(accounts[0].Related_Lead__c, null);
        
        test.stopTest();
    } 
}

 
Christan G 4Christan G 4
Thank you for the quick reply as well Michael! I truly appreciate it. I see the system.assert() methods in this version so now we can start debugging this!

For Code Line 34 (Lines 28 - 34): A Test Generator class called "CreateTestData" was used to generate a test account record. I think the method used within this test class isn't generating the accounts properly which is causing all these other failures to occurs. Sorry to both you again but can you copy and paste the code within that class here as well. I ask because it is importantly for me to understand the logic of these methods when they are being called.
Michael Christie 13Michael Christie 13
Hi Christan.
It's no bother at all - thank you for noticing that. Here is the "CreateTestData" class:
 
/**
 * This class contains the methods to create Test Data.
 */
@isTest
public class CreateTestData {
    
  public static Lead createLeadData(String email) {
        Lead l = new Lead();
        l.FirstName = 'fnTest';
        l.LastName = 'lnTest';
        l.Application_Status__c = Constants.APP_STARTED_STATUS;
        l.Status = 'Open';
        l.Email= email; 
        return l;
    }
    
    public static Lead createLead(String email) {
        Lead l = new Lead();
        l.FirstName = 'fnTest';
        l.LastName = 'lnTest';
        l.Application_Status__c = Constants.APP_STARTED_STATUS;
        l.Status = 'Open';
        l.Email= email;
        l.LeadSource = 'Web - Contact';
        l.Honeypot_Subject__c = '';
        insert l;        
        return l;
    }
    
    public static Lead createLead(String email,String status) {
        Lead l = new Lead();
        l.FirstName = 'fnTest';
        l.LastName = 'lnTest';
        l.Application_Status__c = status;
        l.Status = 'Open';
        l.Email= email;
        l.LeadSource = 'Web - Contact';
        l.Honeypot_Subject__c = '';
        insert l;        
        return l;
    }
    
    public static Account createAccount(String email,String leadId){
      Account a = new Account();
      a.RecordTypeId = Constants.RECORDTYPE_ACCOUNT_APPLICANTS;
      a.FirstName = 'AccFntest';
      a.LastName = 'AccLNTest';
    a.PersonEmail = email;   
        a.AppUserId__c=email;
        a.ExternalReference__c=leadId;
      insert a;
      return a;
    }

    public static Account createAccount(String email){
      Account a = new Account();
      a.RecordTypeId = Constants.RECORDTYPE_ACCOUNT_APPLICANTS;
      a.FirstName = 'AccFntest';
      a.LastName = 'AccLNTest';
    a.PersonEmail = email;   
        a.AppUserId__c=email;
      insert a;
      return a;
    }
    
    public static Opportunity createOpportunity(Account a){
      Opportunity o = new Opportunity();
      o.App_User_ID__c=a.AppUserId__c;
        o.AccountId = a.Id;
      o.StageName = 'Application Started';
      o.Name = 'test';
      o.Opportunity_Date__c = Date.newInstance(2014,02,15);
      o.CloseDate = Date.newInstance(2015,02,15);
      insert o;
      return o;
    }
}

Please feel free to let me know if you need anything else. 
Christan G 4Christan G 4
Line Code 34: What caused this to fail is the wrong field API was being referenced in the system.assert() method. It should have referenced "ExternalReference__c" and not "Related_Lead__c". Please replace lines 31 to 34 in "Test_AccountTriggerHandler" with the following code to resolve this issue: 
List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];     

//Account object should have correct LeadId
System.assertEquals(accounts[0].ExternalReference__c, externalRef);

Line 55: Same issue as above but has a few more errors which needs to be corrected:

Please replace lines 44-46 in "Test_AccountTriggerHandler" with the following code:
String externalLeadRef=String.valueOf(lead.Id);

//Create an account with different email address
Account acc = CreateTestData.createAccount('U_test1@tntp.org',externalLeadRef);

Please replace lines 52-55 in "Test_AccountTriggerHandler" with the following code: 
List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org']; 

//Account object should have correct LeadId 
System.assertEquals(accounts[0].ExternalReference__c, externalRef);

The changes I recommended above should resolve the two errors that were being thrown. Please inform me the outcome when you get a chance.
Michael Christie 13Michael Christie 13
Hi Christan,
Thank you for your help thus far. I deployed AccountTrigger (as inactive), AccountTriggerHandler, CreateTestData, and Test_AccountTriggerHandler (with your corrections) in a change set and received one new error on line 61 of Test_AccountTriggerHandler.
Screenshot Line 61
Class Name: Test_AccountTriggerHandler
Method Name: Account_Gets_Linked_To_Lead_Based_On_Account_Email
Error Message: System.ListException: List index out of bounds: 0
Stack Trace: Class.Test_AccountTriggerHandler.Account_Gets_Linked_To_Lead_Based_On_Account_Email: line 61, column 1

Here is the updated Test_AccountTriggerHandler, for reference: 
@isTest
private class Test_AccountTriggerHandler {

  static RecordType applicantRecordType;
  
  static {
    applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
  }

    static testMethod void testAccountError() {
        test.startTest();
        
        Account acc = CreateTestData.createAccount('U_testAccount@tntp.org','externalRef');              
        acc.FirstName = 'Test Account3';
        update acc;
        delete acc;
        test.stopTest();
    }
    
    static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test2@tntp.org'); 
        String externalRef=String.valueOf(lead.Id);
    
        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org',externalRef); 
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];     

        //Account object should have correct LeadId
        System.assertEquals(accounts[0].ExternalReference__c, externalRef);


        test.stopTest();
    }    
    
  static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_Email() {
        test.startTest();
        
        //Create a lead
    String externalLeadRef=String.valueOf(lead.Id);

        //Create an account with different email address
        Account acc = CreateTestData.createAccount('U_test1@tntp.org',externalLeadRef);

        
        //Get Lead from database
        List<Lead> leads = [Select l.Id,Account__c From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org']; 

        //Account object should have correct LeadId 
        System.assertEquals(accounts[0].ExternalReference__c, externalLeadRef);

        
        //Lead object should have correct AccountId
        System.assertEquals(leads[0].Account__c, accounts[0].Id);
        
        test.stopTest();
    }    
    
    static testMethod void Account_Doesnot_Get_Linked_To_Lead_Because_Of_Missing_Account_ExternalReference() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test2@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test2@tntp.org'];      
    
        //Should find no match
        System.assertEquals(accounts[0].Related_Lead__c, null);
        
        test.stopTest();
    } 
}
Please let me know if I can provide any other information and thank you, again, in advance. 
Christan G 4Christan G 4
Hi Michael, I hope you are well!

I noticed when you pasted the code to replace lines 44-46 that you accidentally also replaced line 43. Please the following code above line 44 and see if this resolves the issue that you are experiencing.
 
Lead lead= CreateTestData.createLead('U_test1@tntp.org');
Michael Christie 13Michael Christie 13
My apologies for that omission. By re-adding that line, it resolved the error message, but now I am getting a new one for that same line (aside from the coverage message):
Screenshot Line 61 2nd Error
Class Name: Test_AccountTriggerHandler
Method Name: Account_Gets_Linked_To_Lead_Based_On_Account_Email
Error Message: System.AssertException: Assertion Failed: Expected: null, Actual: 0011Y000035xFBxQAM
Stack Trace: Class.Test_AccountTriggerHandler.Account_Gets_Linked_To_Lead_Based_On_Account_Email: line 61, column 1

Updated Test_AccountTriggerHandler:
@isTest
private class Test_AccountTriggerHandler {

  static RecordType applicantRecordType;
  
  static {
    applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
  }

    static testMethod void testAccountError() {
        test.startTest();
        
        Account acc = CreateTestData.createAccount('U_testAccount@tntp.org','externalRef');              
        acc.FirstName = 'Test Account3';
        update acc;
        delete acc;
        test.stopTest();
    }
    
    static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_ExternalReference_But_With_Different_Emails() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test2@tntp.org'); 
        String externalRef=String.valueOf(lead.Id);
    
        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test1@tntp.org',externalRef); 
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org'];     

        //Account object should have correct LeadId
        System.assertEquals(accounts[0].ExternalReference__c, externalRef);


        test.stopTest();
    }    
    
  static testMethod void Account_Gets_Linked_To_Lead_Based_On_Account_Email() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org');
        String externalLeadRef=String.valueOf(lead.Id);

        //Create an account with different email address
        Account acc = CreateTestData.createAccount('U_test1@tntp.org',externalLeadRef);

        
        //Get Lead from database
        List<Lead> leads = [Select l.Id,Account__c From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c, a.ExternalReference__c From Account a Where a.PersonEmail ='U_test1@tntp.org']; 

        //Account object should have correct LeadId 
        System.assertEquals(accounts[0].ExternalReference__c, externalLeadRef);

        //Lead object should have correct AccountId
        System.assertEquals(leads[0].Account__c, accounts[0].Id);
        
        test.stopTest();
    }    
    
    static testMethod void Account_Doesnot_Get_Linked_To_Lead_Because_Of_Missing_Account_ExternalReference() {
        test.startTest();
        
        //Create a lead
        Lead lead= CreateTestData.createLead('U_test1@tntp.org'); 

        //Createa a an account with different email address
        Account acc  = CreateTestData.createAccount('U_test2@tntp.org','someinvalidId'); 
        
        //Get Lead from database
        List<Lead> leads = [Select l.Id From Lead l Where l.Email ='U_test1@tntp.org'];  
        
        //Get account from database
        List<Account> accounts = [Select a.PersonEmail,a.Id,a.Related_Lead__c From Account a Where a.PersonEmail ='U_test2@tntp.org'];      
    
        //Should find no match
        System.assertEquals(accounts[0].Related_Lead__c, null);
        
        test.stopTest();
    } 
}

 
Christan G 4Christan G 4
Hi Michael, thank you for the quick response

Please replace code line 61 with the following:
//System.assertEquals(leads[0].Account__c, accounts[0].Id); - Previous code line as of 05-23-2020
System.assertEquals(leads[0].Account__c, null);
The fix above is a temporary work around to the issue you are having. In future scope, whoever created this trigger should review the code and try to optimize it if it is still in use. The Test Generator class should also be reviewed. I have seen many inconsistencies and violation of various best practices which is why I am recommending this. 
Michael Christie 13Michael Christie 13
Hi Christan,
Thank you for that fix - the error on code line 61 is resolved. The only remaining issue is that code coverage is still stuck at 65%. This is a legacy trigger that was created by a consulting firm (and, as you expertly pointed out, its work was not vetted for following best practices). Do you have any additions that would at least elevate the code coverage to 75%?
Christan G 4Christan G 4
Hi Michael, I was reviewing your initial post and saw that you wanted to actually to disable this trigger. I know one way you can do this is by replacing the entire code in the Trigger with the following:
trigger AccountTrigger on Account (before delete, before insert, before update,after insert) {

/*
- Commented out on 05-23-2020
AccountTriggerHandler.execute(Trigger.new, Trigger.newMap, Trigger.old, Trigger.oldMap, 
                          Trigger.isInsert, Trigger.isUpdate, Trigger.isDelete, Trigger.isBefore, Trigger.isAfter);
    AccountTriggerHandler.executeLeadLink(Trigger.new,Trigger.old,Trigger.isUpdate,Trigger.isBefore,Trigger.isInsert,Trigger.isAfter);

*/
}
The trigger would still show as active and will still fire but it won't actually make any changes since its entire body of code would be commented out.

If, however, you want the trigger to appear as inactive in Production then you would first need to deactivate it in the sandbox you are deploying from and then add it to the change set. I believe the code would still need to have a 75% overall test coverage through.
Michael Christie 13Michael Christie 13
Hi Christan,
Yes, that is correct. This trigger no longer needs to be active in Production. However, when I comment out the trigger's code and send it to Production as the only component in a change set I get the same code line errors as before (lines 55 and 34 of Test_AccountTriggerHandler, which were fixed in the sandbox) and the code coverage error. I think increasing the overall test coverage to at least 75% will fix this issue, but I'm unsure how to do that. 
Christan G 4Christan G 4
Okay. We first have to see which lines of code still needs test coverage within that handler class. Please follow the steps below in the sandbox where we made all those exception fixes.

1). Open Developer Console:
User-added image


2). Click on the "Test" tab and then click, "New Run"
User-added image

3). Choose "Test_AccountTriggerHandler" test class from the catalogue on the left side. In the middle column, you will see a grey box next to "Name". Click on it and ensure all checkboxes below it are checked. Finally, click on the "Run" button.
User-added image

4). After the testing executes, click on the "Test" tab and on the bottom right, you'll see a section called "Overall Code Coverage"
User-added image

5). Click on the "AccountTriggerHandler" class. When it opens, you will see that some code is outlined in grey-blue color while others are outlined in red. The lines of code outlined in red are the ones we need to add additional test coverage to. Please provide a screenshot of some of the code that is marked in red. Below is an example of what you see:
User-added image
 
Michael Christie 13Michael Christie 13
Thank you for the detailed instructions and screenshots. Unfortunately, the test run says "AccountTriggerHandler" has 0% coverage, so no lines are being highlighted. 

Code Coverage Screenshot
Here is the class' code: 
public with sharing class AccountTriggerHandler {
	
	static RecordType applicantRecordType;
	static Profile adminProfile;
	static {
		applicantRecordType = [Select Id From RecordType Where Name = 'Applicants' and sobjecttype = 'Account']; 
		adminProfile = [Select Id, Name From Profile Where Name = 'System Administrator'];
	}
	
	public static void execute(List<Account> newList, Map<Id, Account> newMap,
                               List<Account> oldList, Map<Id, Account> oldMap,
                               Boolean isInsert, Boolean isUpdate, Boolean isDelete, Boolean isBefore, Boolean isAfter) {    
    	List<Account> accList = new List<Account>();
    	if (isDelete) {
    		for (Account acc : oldList)
    			accList.add(acc);
    	}
    	else {
    		for (Account acc : newList)
    			accList.add(acc);
    	}    	
    	for (Account acc : accList)	{
    		if (isBefore) {
	    		if (acc.RecordTypeId == applicantRecordType.Id && 
	    			System.Userinfo.getProfileId() != adminProfile.Id) {	    		
	    			acc.addError('Only System Administrators may create, edit, or delete Applicants');		
	    		}
    		}
    	}		                           	
    }
    
	public static Map<String,Lead> GetLeadsWithAccountEmailAddress(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountEmails=new Set<String>();
        for(Account a:accounts){
			accountEmails.add(a.PersonEmail.toLowerCase());
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Email in:accountEmails];   		
        for(Lead lead:leads){
           mappedLeads.put(lead.Email.toLowerCase(),lead);
        }
        return mappedLeads;
    }

	public static Map<String,Lead> GetLeadsWithAccountExternalReference(List<Account> accounts){
        Map<String,Lead> mappedLeads=new Map<String,Lead>();
        Set<String> accountExternalRef=new Set<String>();
        for(Account a:accounts){
            if (!String.isBlank(a.ExternalReference__c)){
                accountExternalRef.add(a.ExternalReference__c);
            }			
        }
        List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:accountExternalRef];   	
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }
        return mappedLeads;
    }    
    
    public static Map<String,Lead> GetLeadsWithAccountRelation(List<Account> accounts){
		Set<Id> leadIds=new Set<Id>();
        Map<String,Lead> mappedLeads=new Map<String,Lead>();   
        for(Account acc:accounts){
            leadIds.add(acc.Related_Lead__c);
        }        
		List<Lead> leads = [Select l.IsConverted, l.Id, l.Email,l.Account__c,l.Application_Status__c
                            From Lead l
                            where l.IsConverted = false and l.Id in:leadIds];	
        for(Lead lead:leads){
           mappedLeads.put(String.valueOf(lead.Id),lead);           
        }   
        return mappedLeads;
    }
    
	public static void CreateLeadLinkAndUpdateLeadData(List<Account> newList,Boolean updateAccount){
        Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
        Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);
        
        if (mappedLeads.size()==0 &&  mappedLeadsByExternalReference.size()==0){
            return;
        }        
        List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:newList){   
            //Check the external ref first
            Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
            if (lead==null){
                lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
            } 
            if (lead!=null){ 
                if (updateAccount && lead.Account__c==null){
                    acc.Related_Lead__c=lead.id;
                }                
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }
        if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }
    } 
	
    public static void UpdateLeadData(List<Account> accList){
        Map<String,Lead> mappedLeads=GetLeadsWithAccountRelation(accList);
        
		List<Lead> updatedLeads=new List<Lead>();
        for(Account acc:accList){   
            Lead lead=mappedLeads.get(acc.Related_Lead__c);
            if (lead!=null){           
                FieldMapperHelper.AccountToLeadMapping(lead,acc); 
                updatedLeads.add(lead);
            }
        }  
		if (updatedLeads.size()>0){
            System.debug('Account insert/update updating lead');                
            update updatedLeads;
        }        
    }
    
	public static void executeLeadLink(List<Account> newList, List<Account> oldList,Boolean isUpdate,Boolean isBefore,Boolean isInsert,Boolean isAfter){      
        if(isInsert && isBefore){     
            Map<String,Lead> mappedLeadsByExternalReference=GetLeadsWithAccountExternalReference(newList);
            Map<String,Lead> mappedLeads=GetLeadsWithAccountEmailAddress(newList);      
            for(Account acc:newList){                
                Lead lead=mappedLeadsByExternalReference.get(acc.ExternalReference__c);
                if (lead==null){
                    lead=mappedLeads.get(acc.PersonEmail.toLowerCase());
                }  
                //Check if lead is not null and lead does not have an account already associated with it
                if (lead!=null && lead.Account__c==null){
                    acc.Related_Lead__c=lead.Id;
                }
                acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);
            }
        } 
        if (isInsert && isAfter){           
            CreateLeadLinkAndUpdateLeadData(newList,false);
        }        
        if (isBefore && isUpdate){
			List<Account> accWithNoLeads=new List<Account>();
			List<Account> accWithLeads=new List<Account>();			
		    for(Account acc:newList)
		 	{
		       	acc.RecordTypeId = FieldMapperHelper.MarkPlusApplicants(acc);		       
				if (acc.Related_Lead__c==null){
					accWithNoLeads.add(acc);						
		       	}
		       	else{
		       		accWithLeads.add(acc);
		       	}
		 	}
         	
         	//Send the accounts that do not have leads - we need to search if leads exists and then link the lead
			CreateLeadLinkAndUpdateLeadData(accWithNoLeads,true);	
            
            //If the account already has a lead, just update the lead no need to relink the accounts
            UpdateLeadData(accWithLeads);
        }
    }    
}
Christan G 4Christan G 4
Hi Michael, I believe this is due to us commenting out the code in the Trigger. Please remove the /* and */ from the trigger code or replace it entirely with the code below. Save the changes and try running the test class again.
trigger AccountTrigger on Account (before delete, before insert, before update,after insert) {

- Commented out on 05-23-2020
AccountTriggerHandler.execute(Trigger.new, Trigger.newMap, Trigger.old, Trigger.oldMap, 
                          Trigger.isInsert, Trigger.isUpdate, Trigger.isDelete, Trigger.isBefore, Trigger.isAfter);
    AccountTriggerHandler.executeLeadLink(Trigger.new,Trigger.old,Trigger.isUpdate,Trigger.isBefore,Trigger.isInsert,Trigger.isAfter);

}
Michael Christie 13Michael Christie 13
Ah, that makes sense! Thank you. I removed the comments from the trigger, re-ran the test, and it looks like 3 lines of code are highlighted in red.

Line 26: 
Line 26 Error

And Lines 91 & 95:
Lines 91 and 95
Christan G 4Christan G 4
Thank You Michael! Currently, I am cleaning. Once I finish, I’ll start reviewing and writing addition test code for the lines marked in red. I apologize for the inconvenience in advance!
Michael Christie 13Michael Christie 13
Of course, Christan! No apologies are necessary. Your help has been incredible and invaluable throughout this, and I really appreciate it. Please take your time.

Thank you,
Michael
Christan G 4Christan G 4
Hi Michael, thank you again for understanding. I started reviewing the "Overall Code Coverage" section in your screenshots and realized something. The overall test coverage for that one trigger class is 96% which is more than enough coverage to migrate this to Production. If you are still getting an error stating that there is less than 75% code coverage when trying to deploy to Production, then this indicates that there is another class which is bringing the overall test coverage down.

In order to deploy to Production, the overall test code coverage needs to be above 75% and none of the Apex test class could fail. We fixed half of the problem by addressing all those exception errors. Now we have to figure out what other code needs additional test code coverage to bring the overall percentage above 75%.

If it is more convenient for you, I can provide you my email and schedule a Zoom meeting to further troubleshoot this together. I know we've been chatting back and forth for awhile so I just wanted to give you this option if you want a quicker fix.

Thanks again for understanding and I look forward to hearing back from you soon!
This was selected as the best answer
Michael Christie 13Michael Christie 13
Hi Christan, yes, I can definitely do a Zoom meeting if that would be easiest. I am on EST in the U.S., but my schedule is flexible and would be happy to meet whenever is most convenient for you. 
kousik maji 7kousik maji 7
Ah, that makes sense! Thank you. I removed the comments from the trigger, re-ran the test, and it looks like 3 lines of code are highlighted in red.https://bengalisms.com/bengali-sad-shayari/