+ Start a Discussion
Greg RohmanGreg Rohman 

Unit Test for Trigger that sends email?

Hello.

I have a trigger on Leads that, when a lead is entered or modified, it checks for any potential duplicate leads in the system. If it finds any, it sends an email to an administrator. The code for the trigger is below.

How do I write unit tests for a trigger like this? What exactly am I testing for? I've written a number of other unit tests for triggers across other objects, both default and custom, and have achieved 100% coverage, but I can't figure out what I should be testing for.

Thanks in advance.

Code:
trigger trigDupeLeadEmailAlert on Lead (before insert, before update) {

    List<Lead> changedLead = new List<Lead>(); // List of the changed leads
    List<Lead> dupeLead = new List<Lead>(); // hold dupes being entered.
    List<Lead> searchResults;
    
    for(Lead le: Trigger.new) {
        changedLead.add(le);
    }

    // Loop on the changed Leads, building the query based on the entered info
    for (Lead cl : changedLead) {
        // Only check if a new record, or if it's an update and the name or company has changed.
        if (Trigger.isInsert || ((cl.LastName != Trigger.oldMap.get(cl.Id).LastName) || (cl.Company != Trigger.oldMap.get(cl.Id).Company) )) {
            String queryString = 'SELECT Id,Name,Company,Email,Owner.Name FROM Lead WHERE IsConverted=False';
            queryString = queryString + ' AND Lead.LastName LIKE \'%' + String.escapeSingleQuotes(cl.LastName) + '%\'';
            queryString = queryString + ' AND Lead.Company LIKE \'%' + String.escapeSingleQuotes(cl.Company) + '%\'';
            queryString = queryString + ' ORDER BY LastName ASC';
            searchResults = Database.query(queryString);
            for (Integer i = 0; i < searchResults.size(); ++i) {    
                dupeLead.add(searchResults[i]);
            }
        }

        // If the dupeLead list contains dupes, create a messaging object and send
        if (dupeLead.size() > 0) {

            // First get the owner of the lead being added
            User leadOwner = [SELECT Name,Email FROM User WHERE Id=:cl.OwnerId];

            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            String[] toAddresses = new String[] {'xxxxxx@xxxxxxxxxxx.com'}; 
            mail.setToAddresses(toAddresses);
            mail.setReplyTo('xxxx@xxxxxxxxxxxx.com');
            mail.setSenderDisplayName('Salesforce Support');
            mail.setSubject('Duplicate Lead Entered');
            mail.setUseSignature(false);
            
            String sendDate = Datetime.now().format('MM.dd.yyyy');
            String MailBodyHTML;
            MailBodyHTML = '<html><body style="font-family: Arial; font-size: 9pt;">';
            MailBodyHTML = MailBodyHTML + sendDate + '<br/>';
            MailBodyHTML = MailBodyHTML + '<font size=+1><strong>Salesforce.com: Potential Duplicate Prospect</strong></font><br/><br/>';
            MailBodyHTML = MailBodyHTML + 'The following Prospect was just entered or modified in Salesforce by <strong>' + leadOwner.Name + '</strong>.<br/><br/>';
            MailBodyHTML = MailBodyHTML + '<table border="1" cellpadding="4" cellspacing="0" style="font-family: Arial; font-size: 9pt;"><tr>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Prospect Name<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Company<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Email Address<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Link<strong></td>';
            MailBodyHTML = MailBodyHTML + '</tr>';
            MailBodyHTML = MailBodyHTML + '<tr><td>'+ cl.FirstName + ' ' + cl.LastName + '</td><td>' + cl.Company + '</td>';
            MailBodyHTML = MailBodyHTML + '<td>'+ cl.Email + '</td>';
            MailBodyHTML = MailBodyHTML + '<td><a href="https://na1.salesforce.com/'+ cl.Id + '" target="_blank">View Prospect</a></td></tr>';
            MailBodyHTML = MailBodyHTML + '</table>';
            MailBodyHTML = MailBodyHTML + '</br><br/>Similar prospects are listed below. Please check to make sure there aren\'t any conflicts.</br><br/>';

            MailBodyHTML = MailBodyHTML + '<table border="1" cellpadding="4" cellspacing="0" style="font-family: Arial; font-size: 9pt;"><tr>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Prospect Name<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Company<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Email Address<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Owner<strong></td>';
            MailBodyHTML = MailBodyHTML + '<td><strong>Link<strong></td>';
            MailBodyHTML = MailBodyHTML + '</tr>';
     // Loop on the dupes
for (Lead ol : dupeLead) { MailBodyHTML = MailBodyHTML + '<tr><td>'+ ol.Name + '</td><td>' + ol.Company + '</td>'; MailBodyHTML = MailBodyHTML + '<td>'+ ol.Email + '</td><td>' + ol.Owner.Name + '</td>'; MailBodyHTML = MailBodyHTML + '<td><a href="https://na1.salesforce.com/'+ ol.Id + '" target="_blank">View Prospect</a></td></tr>'; } MailBodyHTML = MailBodyHTML + '</table>'; MailBodyHTML = MailBodyHTML + '</body></html>'; mail.setHtmlBody(MailBodyHTML); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } } }

 -Greg

Best Answer chosen by Admin (Salesforce Developers) 
jeffdonthemicjeffdonthemic
I wrote a blog post on this exact same subject, aptly titled, "How to Unit Test Sending Mail in Apex". I hope it helps you out.

http://blog.jeffdouglas.com/2008/10/15/how-to-unit-test-sending-mail-in-apex/

Jeff Douglas
Informa Plc
http://blog.jeffdouglas.com

All Answers

jeffdonthemicjeffdonthemic
I wrote a blog post on this exact same subject, aptly titled, "How to Unit Test Sending Mail in Apex". I hope it helps you out.

http://blog.jeffdouglas.com/2008/10/15/how-to-unit-test-sending-mail-in-apex/

Jeff Douglas
Informa Plc
http://blog.jeffdouglas.com

This was selected as the best answer
Greg RohmanGreg Rohman
Hi Jeff.

Thanks, this worked nicely.

Interestingly enough, the rest of my trigger was also not being covered. In all of my other triggers, I was always committing data to objects, so I was always able to use System.assertEquals to make sure those changes were made. In the trigger above, there isn't any data being saved to objects, so I didn't know how to get coverage on those things. My solution was simply to create a duplicate lead in my test method... that's it. Two lines of code, and it covered 100%.

I don't quite understand why or how that is... but it worked. /shrug

Thanks again.

-Greg
jeffdonthemicjeffdonthemic
Yes... unit testing is .... ummm .... interesting!?
 
Glad things turned out well. Have a great day.
 
Jeff Douglas
Informa Plc
Rasmus MenckeRasmus Mencke
As long as all the lines of your code is touched when the test is run, you should be fine - if the trigger always will send the email, you should be ok.