Preface: This video is part 3 of the Official #Apex4Admins series presented by Salesforce and I!
Combine your knowledge from part 1 and 2 to write an epic deduping trigger!
Lists
List<Food__c> dollarMenu = [SELECT Id, Name FROM Food__c WHERE Price__c = 1];Food__c firstItem = dollarMenu[0]; // McChicken Food__c secondItem = dollarMenu[1]; // Sausage Biscuit Food__c thirdItem = dollarMenu[2]; // McDouble Food__c fourthItem = dollarMenu[3]; // Hash BrownsList<String> buddies = new List<String>();buddies.add('Ronald McDonald'); buddies.add('Hamburglar'); buddies.add('Mayor McCheese'); buddies.add('Officer Big Mac');
Dot Notation
// Use Case #1: Access fields String sandwichName = dollarMenu[0].Name; // Use Case #2: Traverse relationships String me = dollarMenu[0].Eaten_By__r.Name; // Use Case #3: Access methods!dollarMenu.remove(2); // Farewell McDouble// Every data type has methods! Food__c newItem = new Food__c();newItem.Name = 'bbq Ranch Burger'.capitalize();dollarMenu.add(newItem);
Bind Variables
// Use variables inside your SOQL queries! String bestMcDonaldsItem = 'Chocolate Dipped Ice Cream Cone'; List<Food__c> bestItems = [SELECT Id, Name FROM Food__cWHERE Name = :bestMcDonaldsItem];// You can use Lists as Bind Variables too List<String> dietFoodNames = new List>(); dietFoodNames.add('Apple Slices'); dietFoodNames.add('Side Salad'); dietFoodNames.add('Fruit & Yogurt Parfait'); List<Food__c> bannedFoods = [SELECT Id, Calories__c FROM Food__c WHERE Name IN :dietFoodNames];
Test Class Principle #1: Create Records from Scratch
Contact dupeContact = new Contact();dupeContact.LastName = 'Spiderman';dupeContact.Email = 'spiderman@gmail.com';insert dupeContact;Lead dupeLead = new Lead();dupeLead.FirstName = 'Peter'; dupeLead.LastName = 'Parker'; dupeLead.Company = 'Daily Bugle';dupeLead.Email = 'spiderman@gmail.com';insert dupeLead;
Test Class Principle #2: Use System.assertEquals()
// Example: This obviously comes out to trueSystem.assertEquals(true, bestWebinarEver);// Example: This will give you an error and fail your test class!System.assertEquals('Tom Brady', bestActiveQuarterback);// Query the post-trigger values and assert assumptions dupeLead = [SELECT Id, Dupe_Contact__c FROM Lead WHERE Email = :dupeLead.Email LIMIT 1];System.assertEquals(dupeContact.Id, dupeLead.Dupe_Contact__c);
Test Class Principle #3: Test Negative Scenarios Too!
// Create a lead that SHOULDN'T have a dupe Lead uniqueLead = new Lead(); uniqueLead.LastName = 'Xavier'; uniqueLead.Company = 'X-Men';uniqueLead.Email = 'theprofessor@xmen.com';insert uniqueLead; // Assert that a dupe isn't identified on the lead uniqueLead = [SELECT Id, Dupe_Contact__c FROM Lead WHERE Email = :uniqueLead.Email LIMIT 1];System.assertEquals(null, uniqueLead.Dupe_Contact__c);
Test Class Principle #4: Test in Bulk!
// Add 200 new Contacts to a listList<Contact> dupeContacts = new List<Contact>();for (Integer i = 0; i < 200; i++) { Contact c = new Contact(); c.FirstName = 'David'; c.LastName = String.valueOf(i); c.Email = 'contact' + c.LastName + '@gmail.com';dupeContacts.add(c);} // Insert all 200 contacts at the same timeinsert dupeContacts;
Deduping Trigger
// Populate a Contact Lookup field if there's a dupe! trigger DetectDupes on Lead (before insert, before update) { for (Lead l : Trigger.new) { if (l.Email != null) { String leadEmail = l.Email;List<Contact> dupeContacts = [SELECT Id FROM Contactif (dupeContacts.size() > 0) {
WHERE Email = :l.Email];l.Dupe_Contact__c = dupeContacts[0].Id;} else { l.Dupe_Contact__c = null; } } else { l.Dupe_Contact__c = null; } } }
Deduping Trigger Test Class
@isTest public class TestDeduper { static testMethod void testDupes() { // Principle #1: Create records from scratch!Contact dupeContact = new Contact();dupeContact.LastName = 'Spiderman'; dupeContact.Email = 'spiderman@gmail.com'; insert dupeContact;Lead dupeLead = new Lead();dupeLead.FirstName = 'Peter'; dupeLead.LastName = 'Parker'; dupeLead.Company = 'Daily Bugle'; dupeLead.Email = 'spiderman@gmail.com'; insert dupeLead; // Principle #2: Use System.assertEquals() dupeLead = [SELECT Id, Dupe_Contact__c FROM Lead WHERE Email = :dupeLead.Email LIMIT 1];System.assertEquals(dupeContact.Id, dupeLead.Dupe_Contact__c);// Principle #3: Test things that shouldn't work! Lead uniqueLead = new Lead(); uniqueLead.LastName = 'Xavier'; uniqueLead.Company = 'X-Men';uniqueLead.Email = 'theprofessor@xmen.com';insert uniqueLead; uniqueLead = [SELECT Id, Dupe_Contact__c FROM Lead WHERE Email = :uniqueLead.Email LIMIT 1];System.assertEquals(null, uniqueLead.Dupe_Contact__c);} }
Hi David,
Thanks for the amazing tutorials and precise content regarding Apex. I am in love with SFDC99 <3.
I just tried following the 4 principles of writing a good test class for this example by creating bulk data as below. When I try to run this class, it gives me 101 SOQL error: System.LimitException: Too many SOQL queries: 101 (at line 15).
I understand, I am trying to create 200 contacts in bulk here but I am inserting the data outside For each loop.
Can you please help me out here?
@isTest
public class myDetectDupesTest
{
static testMethod void createDupes()
{
List listOfBulkContacts= new List();
for(Integer i=0; i<=200; i++)
{
Contact c = new Contact();
c.LastName = 'testDupe' + i;
c.Email = c.LastName + '@gmail.com';
listOfBulkContacts.add(c);
}
insert listOfBulkContacts;
List listOfBulkLeads = new List();
for(Integer k=0; k<=200; k++)
{
Lead l = new Lead();
l.LastName = 'testDupe' + k;
l.Company = 'testDupeCompany' + k;
l.Email = l.LastName + '@gmail.com';
listOfBulkLeads.add(l);
}
insert listOfBulkLeads;
listOfBulkLeads = [SELECT Id, Dupe_Contact__c FROM Lead LIMIT 1];
System.assertequals(listOfBulkContacts[0].Id,listOfBulkLeads[0].Dupe_Contact__c);
}
Your triggers are inefficient =) Not the test class!
Hi David,
The trigger has pretty simple code as described below. Can you please help me find out what’s causing 101 SOQL issue?
trigger myDetectDupes on Lead (before insert,before update) {
for(Lead l: trigger.new)
{
//Ensure Lead has an email
if(l.Email != null)
{
//Take that email into string(Apex variable) to use it in SOQL
String leadEmail = l.Email;
List listDupeContacts = [SELECT Id FROM Contact WHERE Email =: leadEmail];
if(listDupeContacts.size() > 0)
{
l.Dupe_Contact__c = listDupeContacts[0].Id;
}
else
{
l.Dupe_Contact__c = null;
}
}
else
{
l.Dupe_Contact__c = null;
}
}
}
Hi David,
I have been following your videos and they are great! I ran into a bit of a snag though with your deduping trigger.
for (Lead l : Trigger.new) {
I am getting an error message that an equal sign was expected.
I’ve tried this into two different Sandboxes and I am getting the same error message.
Any feedback would be appreciated.
Thank you,
Orchid
Post your code and I’ll take a look!
(Sorry sometimes my site does weird things with code in comments!)