Use Case:

Chaining of Queueable Jobs

When a new Lead is inserted,

  1. Create an account with Name, Industry and BillingAddress same as Lead’s Company, Industry and Address.
  2. Create a Contact with FirstName, LastName, Account same as Lead’s FirstName, LastName and Account’s Name respectively.
trigger LeadTrigger on Lead (after insert) {
if(Trigger.isAfter) {
if(Trigger.isInsert) {
// Call a Queueable apex which would create an account using company's name
QueueableAccount queueableAcc = new QueueableAccount(Trigger.new);
System.enqueueJob(queueableAcc);
}
}
}


public class QueueableAccount implements Queueable {
@TestVisible private static Boolean queueableAccountRun = true;
List<Lead> leadsList = new List<Lead>();
// Constructor to get list of new Leads inserted
public QueueableAccount(List<Lead> leadsList) {
this.leadsList = leadsList;
}
public void execute(System.QueueableContext qc) {
Map<Lead,Account> leadsWithAccounts = new Map<Lead,Account>();
// Add account for each Lead in the list "accountsList" and insert list
for(Lead lead : leadsList) {
Account newAcc = new Account(Name = lead.Company,
Industry = lead.Industry,
BillingStreet = lead.Street,
BillingCity = lead.City,
BillingState = lead.State,
BillingCountry = lead.Country,
BillingPostalCode = lead.PostalCode);
leadsWithAccounts.put(lead, newAcc);
}
insert leadsWithAccounts.values();
// Call QueueableContact to create Contacts from Leads.
if(queueableAccountRun) {
QueueableContact queueableCon = new QueueableContact(leadsWithAccounts);
    System.enqueueJob(queueableCon);
}
}
}


public class QueueableContact implements Queueable {
Map<Lead,Account> leadsWithAccounts = new Map<Lead,Account>();
public QueueableContact(Map<Lead,Account> leadsWithAccounts) {
this.leadsWithAccounts = leadsWithAccounts;
}
public void execute(QueueableContext qc) {
// Create an empty list of contacts
List<Contact> contactsList = new List<Contact>();
// Iterate through each key of Map leadsWithAccounts
for(Lead lead : leadsWithAccounts.keySet()) {
// Get the values from the each Lead and add it into the contactsList
contactsList.add(new Contact(FirstName = lead.FirstName,
LastName = lead.LastName,
AccountId = leadsWithAccounts.get(lead).Id));
}
insert contactsList;
}
}

Test Class:

Note: We can’t chain queueable jobs in an Apex test. Doing so results in an error. So in order to test the functionality, we will write test method for each of the Account and Contact Queueable class.

Test QueueableAccount class – Insert a new Lead. After insertion a new Lead, an Account should be created with Lead’s company name. To avoid running QueueableContact class so that we don’t get the error, we can use @TestVisible boolean value which can control the execution of the class.

Test QueueableContact class – Insert a new Lead and an Account and call QueueableContact class, Contact should be created using the details from Lead and Account.

@isTest
private class LeadTriggerTest {
// This method will only test QueueableAccount class because in chaining only 1 class can be tested at a time to avoid Maximum stack depth error
// After insertion a new Lead, an Account should be created with Lead's company name.
    @isTest
static void testQueueableAccount() {
// Insert new lead
// and set QueueableAccount.queueableAccountRun to false, so that the Contact Queueable class won't be called
// and "Maximum stack depth has been reached." error can be ignored
Lead newLead = new Lead(FirstName = 'Bob',
LastName = 'Marley',
Company = 'Peace Ltd',
Industry = 'Entertainment');
Test.startTest();
    QueueableAccount.queueableAccountRun = false;
    insert newLead;
Test.stopTest();
// Assert that account should be created with same name as Lead's company name
Account acc = [Select Id, Name From Account LIMIT 1];
System.assertEquals(newLead.Company, acc.Name, 'Account created does not have the name same as Lead Company name.');
}
// This method will test QueueableContact class.
// Insert a new Lead and an Account and call QueueableContact class
// Assert the Contact's FirstName, LastName and AccountId
@isTest
static void queueableContactTest() {
// Create a Lead
Lead newLead = new Lead(FirstName = 'Bob',
LastName = 'Marley',
Company = 'Peace Ltd',
Industry = 'Entertainment');
QueueableAccount.queueableAccountRun = false;
insert newLead;
// Create an account
Account acc = new Account(Name = 'Peace Ltd',
Industry = 'Entertainment');
insert acc;
Map<Lead,Account> leadsWithAccounts = new Map<Lead,Account>();
leadsWithAccounts.put(newLead, acc);
// Call QueueableContact class and assert the first name, last name and account id
Test.startTest();
        QueueableContact queueable = new QueueableContact(leadsWithAccounts);
System.enqueueJob(queueable);
Test.stopTest();
Contact con = [Select Id, FirstName, LastName, AccountId From Contact LIMIT 1];
System.assertEquals(newLead.FirstName, con.FirstName, 'Contact First Name does not match with Lead First Name.');
System.assertEquals(newLead.LastName, con.LastName, 'Contact Last Name does not match with Lead First Name.');
System.assertEquals(acc.Id, con.AccountId, 'Contact Account Id does not match with Account created from Lead');
}
}
Code Coverage:
LeadTrigger - 100%
QueueableAccount - 89%
QueueableContact - 100%
Like it ? Share : Do Nothing

Leave a Reply