[SalesForce] Test Class Coverage Issue with Trigger.newMap != Trigger.oldMap

I'm hoping I am missing something obvious.

I have a Lead Trigger & Handler class. The Handler forces Assignment Rules to fire if a Lead Checkbox field IS CHANGED to True. After Update. It is working for users.

The problem is my Handler test class coverage stops right at the line where I am checking whether the field "Attention Required" has been changed to true:

  public class LeadTriggerHandler extends TriggerHandlerFactory{
  private Map<Id, Lead> newLeadMap;
  private Map<Id, Lead> oldLeadMap;

  public LeadTriggerHandler() {
    this.newLeadMap = (Map<Id, Lead>) Trigger.newMap;
    this.oldLeadMap = (Map<Id, Lead>) Trigger.oldMap;
  }

    public override void afterUpdate() {
        try{
        attentionRequiredLeadAssignment();
        }catch(Exception e){
            Utils.CreateSystemException(e);
        }
    }   

  /*
  * If a Lead is set to "Attention Required"
  * and is owned by one of the following Queues: Recycle, Nurture, Junk
  * then trigger Assignment Rules to reassign Lead
  */
  private void attentionRequiredLeadAssignment() {
    List<Lead> leads = new List<Lead>();
    List<String> queueNameList = new List<String>();
    Set<String> queueNameSet = new Set<String>();

    for(Lead l : [SELECT Id,attention_required__c,Owner.Name FROM Lead WHERE Id IN :newLeadMap.keyset()]){
      //if attention required is changed to TRUE
      if(newLeadMap.get(l.id).attention_required__c != oldLeadMap.get(l.id).attention_required__c && newLeadMap.get(l.id).attention_required__c == true){
        //getting Queue names from custom setting
        LeadTriggerHandlerSetting__c setting = LeadTriggerHandlerSetting__c.getValues('AttentionRequired');
        queueNameList = setting.queue_names__c.split(','); 
        queueNameSet.addAll(queueNameList);
        //and lead owner is recycle, nurture, or junk leads
        if(queueNameSet.contains(l.Owner.Name)){
          leads.add(l);
        }
      }
    }

    if(!leads.isEmpty()) {
       Database.DMLOptions dmo = new Database.DMLOptions();
       //force assignment rules to fire
       dmo.assignmentRuleHeader.useDefaultRule = true;
       Database.SaveResult[] lsr = Database.update(leads, dmo);

       Integer i=0;
       for(Database.SaveResult sr : lsr) {
          if(!sr.isSuccess()){
              leads[i].addError('Lead Assignment Error' + sr.getErrors()[0].getMessage());
          }
          i++;
       } 
    }
  }


}

It seems obvious enough that in the Test Class I need to insert a Lead with "Attention Required" set to false, and then update it to true. However this is not getting me coverage past the line:

if(newLeadMap.get(l.id).attention_required__c != oldLeadMap.get(l.id).attention_required__c && newLeadMap.get(l.id).attention_required__c == true){

This is the Test Class:

@isTest
private class LeadTriggerHandlerTest
{
    @isTest
    static void testLeadAssignment() {
        Group testGroup = new Group(Name='Junk Leads', Type='Queue');
        insert testGroup;

        System.runAs(new User(Id=UserInfo.getUserId()))
        {
            QueuesObject testQueue = new QueueSObject(QueueID = testGroup.id, SObjectType = 'Lead');
            insert testQueue;
        }

        LeadTriggerHandlerSetting__c setting = new LeadTriggerHandlerSetting__c();
        setting.Name = 'AttentionRequired';
        setting.Queue_Names__c = 'Junk Leads,Nurture Pool';
        insert setting;

        DataFactory factory = new DataFactory();

        Lead l = factory.createLead();
        l.OwnerId = testGroup.id;
        l.Attention_Required__c = false;
        upsert l;

        l.Attention_Required__c = true;
        update l;
    }
}

Any ideas?

Best Answer

I've seen similar issues when you have recursive trigger control logic implemented in your trigger pattern.

  1. When executed via the UI, it works fine because there are two transactions
  2. When executed in the testmethod, the second update does nothing because it is in the same transaction.

Clear out the static variable used to control recursive triggers between the upsert and update to simulate the user's UI experience

Related Topic