2

I have a trigger to convert Lead to Contact. For some reason it wasn't converting some automated incoming leads. To figure that out, I added Email Messaging so anytime it fails, it will send an error email to me. I am trying to move this to production, however, the test class shows 62% coverage. Apart from creating a validation rule on Contact and failing it, is there any other way in test class I can make the lead conversion fail to increase the code coverage?

Trigger :

trigger convertMarketoLeads on Lead (after insert) 
{
    // added by 501Partners to ensure only Marketo leads are auto-converted
    Id myId = [Select Id From User Where Username like '[email protected]%' limit 1].Id;
    list<String> errors = new list<String>();


    List<Database.LeadConvert> leadCollectionArray = new List<Database.LeadConvert>();
    for(Lead l : trigger.new)
    {
        if(!l.isConverted && l.CreatedByID == myId)
        {
          Database.LeadConvert lc = new database.LeadConvert();
          lc.setLeadId(l.Id);
          lc.setConvertedStatus('Marketing Qualified Lead');
          lc.setDoNotCreateOpportunity(true);
          leadCollectionArray.add(lc);
         }
    }   


    Database.LeadConvertResult[] lcr = Database.convertLead(leadCollectionArray,false);

    // set any created accounts to be 1:1 with their contacts
    List<Account> a = new List<Account>();
    integer resSize = lcr.size();
    for (integer j = 0; j < resSize; ++j) 
    {
        String error='';
        if (lcr[j].isSuccess()) 
        {
            Account tempa = new Account(id=lcr[j].getAccountId(), npe01__SYSTEMIsIndividual__c=TRUE, npe01__One2OneContact__c=lcr[j].getContactId());
            a.add(tempa);
        }

        else{

            error='Error(s) on lead with ID: ' + +lcr[j].getLeadId()+'\n';
            for(Database.Error err: lcr[j].getErrors()){
                error += 'Status Code: ' + err.getStatusCode() + '; Message: ' + err.getMessage() + '\n';
            }
            errors.add(error);
        }
    }
    update a;

    if(!errors.isEmpty()){

         Messaging.SingleEmailMessage mail=new Messaging.SingleEmailMessage();
         String[] toAddresses = new String[] {'[email protected]'};
         mail.setToAddresses(toAddresses);
         mail.setReplyTo('[email protected]');
         mail.setSenderDisplayName('Apex error message');
         mail.setSubject('Error from Org : ' + UserInfo.getOrganizationName());
         String errorBody = String.join(errors, '\n\n');
         mail.setPlainTextBody(errorBody);
         Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
}

Test Class :

@isTest
private class testConvertMarketoLeads
{
    public static testMethod void testConvertMarketoLeads()
    {
       // Setup test data
      User Muser = [Select Id From User Where Username like '[email protected]%' limit 1];

      System.runAs(Muser) 
      {
        List<Lead> newLeads = new List<Lead>();

        for(integer i=0; i<100; i++)
        {
            newLeads.add(new Lead(LastName='Fish' + i, Company='Test Lead'+i));
        }

        insert newLeads;


     //  List<Lead> validateConvertedLeads = [SELECT Id FROM Lead WHERE isConverted = TRUE];
    //   system.assertEquals(100,validateConvertedLeads.size());


      }
    }
}

1 Answer 1

3

This is one of the reasons why we're advised to create a "Trigger Handler" class. This allows us to test the logic independently of actually calling the trigger.

Trigger

trigger LeadTrigger on Lead (after insert) {
  LeadTriggerHandler.run(Trigger.old, Trigger.new);
}

Trigger Handler

public class LeadTriggerHandler {
  // Dispatch method
  public static void run(Lead[] triggerOld, Lead[] triggerNew) {
    if(Trigger.isBefore) {

    } else { // Trigger.isAfter
      if(Trigger.isInsert) {
        afterInsert(triggerOld, triggerNew);
      }
    }
  }
  // DML event handlers
  @TestVisible static void afterInsert(Lead[] triggerOld, Lead[] triggerNew) {
    autoConvertLead(triggerNew);
  }
  // Utility methods
  static void autoConvertLead(Lead[] triggerNew) {
    // Logic to convert lead and email on failure
  }
}

NOTE: Different types of trigger handler frameworks are possible, this is only one of the many simpler types you can use to get started. You can read more about frameworks elsewhere if you're interested.

The main point here is that a handler class allows you to directly call a DML event to test it.

Sample Test Method

@isTest static void testLeadConvertFail() {
  // Purposefully fail
  LeadTriggerHandler.afterInsert(new Lead[] { new Lead() }, new Lead[] { new Lead() });
  // Check to make sure an email was sent
  System.assertEquals(1, Limits.getEmailInvocations());
}

This allows us to purposefully fail the test by passing in a lead without an ID value (because we did not actually insert a new record). The trigger itself is never called, but the logic we're interested in testing can be called directly.

Do make sure that you write a unit test that does test the trigger itself by performing an actual DML operation, but this test can simply be a "happy path" test to make sure that your records can save successfully without running in to governor limits, etc.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .