6

This is scaled down code from SF's own examples on how to find dupe email addresses. I have purpose commented out the Alert for now. There is a more elaborate trigger (that also works in Sandbox) but this keeps things simpler. The problem is in deploying to PRODUCTION (well over 100k records) and errors gotten there...

trigger leadDuplicatePreventer on Lead(before insert) {

    Map<String, Lead> leadMap = new Map<String, Lead>();
    //Create a map of the new leads, excluding any dupes

    for (Lead lead : System.Trigger.new) {
        //Make sure the new leads don't have any duplicates of each other  
        if (lead.Email != null && leadMap.containsKey(lead.Email)) {
            // commented to avoid users being alerted at this time     lead.Email.addError('Another new lead has the same email address.');
        } else {
            leadMap.put(lead.Email, lead);
        }
    }

    //Eliminate any new leads whose emails are already in the system
    for (Lead lead : [SELECT Email FROM Lead WHERE Email IN :leadMap.KeySet()]) {
        Lead newLead = leadMap.get(lead.Email);
        // commented to avoid users being alerted at this time             newLead.Email.addError('A lead with this email address already exists.');
    }
}

This trigger works fine in Sandbox. I have 100s of thousands of records in Production so I have to worry about errors pertaining to queries that are too large. I'm down to a couple errors that I'm just not clear on. In the CLASS below, it is complaining about an Assertion Fail at the first System.assert(false). If I comment out that TRY section, it just complains at the NEXT assert.

  • Failure Message: "System.AssertException: Assertion Failed", Failure Stack Trace: "Class.leadDupePreventerTests_v2.testLeadDupPreventer: line 51, column 1"

There are several lines commented out throughout the class referencing "Email" as well - it will not even work in Sandbox with those active. (sigh) This code must be OLD because it now won't work out of the box from SF's Dev site into Enterprise Release 12 environment.

Help? :-/ Thanks.

public class leadDupePreventerTests_v2{
    static testMethod void testLeadDupPreventer() {

      // First make sure there are no leads already in the system  
      // that have the email addresses used for testing  

      Set<String> testEmailAddress = new Set<String>();
      testEmailAddress.add('test1@duptest.com');
      testEmailAddress.add('test2@duptest.com');
      testEmailAddress.add('test3@duptest.com');
      testEmailAddress.add('test4@duptest.com');
      testEmailAddress.add('test5@duptest.com');
      System.assert([SELECT count() FROM Lead
                     WHERE Email IN :testEmailAddress] == 0);

      // Seed the database with some leads, and make sure they can  
      // be bulk inserted successfully.  

      Lead lead1 = new Lead(LastName='Test1', Company='Test1 Inc.',
                            Email='test1@duptest.com');
      Lead lead2 = new Lead(LastName='Test2', Company='Test2 Inc.',
                            Email='test4@duptest.com');
      Lead lead3 = new Lead(LastName='Test3', Company='Test3 Inc.',
                            Email='test5@duptest.com');
      Lead[] leads = new Lead[] {lead1, lead2, lead3};
      insert leads;

      // Now make sure that some of these leads can be changed and  
      // then bulk updated successfully. Note that lead1 is not  
      // being changed, but is still being passed to the update  
      // call. This should be OK.  

      lead2.Email = 'test2@duptest.com';
      lead3.Email = 'test3@duptest.com';
      update leads;

      // Make sure that single row lead duplication prevention works  
      // on insert.  

      Lead dup1 = new Lead(LastName='Test1Dup',
                           Company='Test1Dup Inc.',
                           Email='test1@duptest.com');
      try {
         insert dup1;
         System.assert(false);
      } catch (DmlException e) {
         System.assert(e.getNumDml() == 1);
         System.assert(e.getDmlIndex(0) == 0);
         System.assert(e.getDmlFields(0).size() == 1);
         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'A lead with this email address already exists.') > -1);
      }

      // Make sure that single row lead duplication prevention works  
      // on update.  

      dup1 = new Lead(Id = lead1.Id, LastName='Test1Dup',
                      Company='Test1Dup Inc.',
                      Email='test2@duptest.com');
      try {
         update dup1;
         System.assert(false);
      } catch (DmlException e) {
         System.assert(e.getNumDml() == 1);
         System.assert(e.getDmlIndex(0) == 0);
         System.assert(e.getDmlFields(0).size() == 1);
//         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'A lead with this email address already exists.') > -1);
        }

      // Make sure that bulk lead duplication prevention works on  
      // insert. Note that the first item being inserted is fine,  
      // but the second and third items are duplicates. Note also  
      // that since at least one record insert fails, the entire  
      // transaction will be rolled back.  

      dup1 = new Lead(LastName='Test1Dup', Company='Test1Dup Inc.',
                      Email='test4@duptest.com');
      Lead dup2 = new Lead(LastName='Test2Dup',
                           Company='Test2Dup Inc.',
                           Email='test2@duptest.com');
      Lead dup3 = new Lead(LastName='Test3Dup',
                           Company='Test3Dup Inc.',
                           Email='test3@duptest.com');
      Lead[] dups = new Lead[] {dup1, dup2, dup3};
      try {
         insert dups;
         System.assert(false);
      } catch (DmlException e) {
         System.assert(e.getNumDml() == 2);
         System.assert(e.getDmlIndex(0) == 1);
         System.assert(e.getDmlFields(0).size() == 1);
//         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'A lead with this email address already exists.') > -1);
         System.assert(e.getDmlIndex(1) == 2);
         System.assert(e.getDmlFields(1).size() == 1);
//         System.assert(e.getDmlFields(1)[0] == 'Email');
         System.assert(e.getDmlMessage(1).indexOf(
            'A lead with this email address already exists.') > -1);
      }

      // Make sure that bulk lead duplication prevention works on  
      // update. Note that the first item being updated is fine,  
      // because the email address is new, and the second item is  
      // also fine, but in this case it's because the email  
      // address doesn't change. The third case is flagged as an  
      // error because it is a duplicate of the email address of the  
      // first lead's value in the database, even though that value  
      // is changing in this same update call. It would be an  
      // interesting exercise to rewrite the trigger to allow this  
      // case. Note also that since at least one record update  
      // fails, the entire transaction will be rolled back.  

      dup1 = new Lead(Id=lead1.Id, Email='test4@duptest.com');
      dup2 = new Lead(Id=lead2.Id, Email='test2@duptest.com');
      dup3 = new Lead(Id=lead3.Id, Email='test1@duptest.com');
      dups = new Lead[] {dup1, dup2, dup3};
      try {
         update dups;
         System.assert(false);
      } catch (DmlException e) {
         System.debug(e.getNumDml());
         System.debug(e.getDmlMessage(0));
         System.assert(e.getNumDml() == 1);
         System.assert(e.getDmlIndex(0) == 2);
         System.assert(e.getDmlFields(0).size() == 1);
//         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'A lead with this email address already exists.') > -1);
        }

      // Make sure that duplicates in the submission are caught when  
      // inserting leads. Note that this test also catches an  
      // attempt to insert a lead where there is an existing  
      // duplicate.  

      dup1 = new Lead(LastName='Test1Dup', Company='Test1Dup Inc.',
                      Email='test4@duptest.com');
      dup2 = new Lead(LastName='Test2Dup', Company='Test2Dup Inc.',
                      Email='test4@duptest.com');
      dup3 = new Lead(LastName='Test3Dup', Company='Test3Dup Inc.',
                      Email='test3@duptest.com');
      dups = new Lead[] {dup1, dup2, dup3};
      try {
         insert dups;
         System.assert(false);
      } catch (DmlException e) {
         System.assert(e.getNumDml() == 2);
         System.assert(e.getDmlIndex(0) == 1);
         System.assert(e.getDmlFields(0).size() == 1);
//         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'Another new lead has the same email address.') > -1);
         System.assert(e.getDmlIndex(1) == 2);
         System.assert(e.getDmlFields(1).size() == 1);
//         System.assert(e.getDmlFields(1)[0] == 'Email');
         System.assert(e.getDmlMessage(1).indexOf(
            'A lead with this email address already exists.') > -1);
      }

      // Make sure that duplicates in the submission are caught when  
      // updating leads. Note that this test also catches an attempt  
      // to update a lead where there is an existing duplicate.  

      dup1 = new Lead(Id=lead1.Id, Email='test4@duptest.com');
      dup2 = new Lead(Id=lead2.Id, Email='test4@duptest.com');
      dup3 = new Lead(Id=lead3.Id, Email='test2@duptest.com');
      dups = new Lead[] {dup1, dup2, dup3};
      try {
         update dups;
         System.assert(false);
      } catch (DmlException e) {
         System.assert(e.getNumDml() == 2);
         System.assert(e.getDmlIndex(0) == 1);
         System.assert(e.getDmlFields(0).size() == 1);
//         System.assert(e.getDmlFields(0)[0] == 'Email');
         System.assert(e.getDmlMessage(0).indexOf(
            'Another new lead has the same email address.') > -1);
         System.assert(e.getDmlIndex(1) == 2);
         System.assert(e.getDmlFields(1).size() == 1);
//         System.assert(e.getDmlFields(1)[0] == 'Email');
         System.assert(e.getDmlMessage(1).indexOf(
            'A lead with this email address already exists.') > -1);
      }
   }
}
  • 1
    Just to be clear, are the addError() calls commented when you run the test? As far as I can see, that first assert(false) would fail, since there's no error being set on the dupe insertion. – metadaddy Sep 6 '12 at 14:55
  • This code is as-is, no extra commenting being done. :-/ I'm not clear on how to set the error (I'm about a level 1.5 out of 10 right now in the Apex world, learning the hard way). – AMM Sep 6 '12 at 15:08
7

You can't comment out the errors or the test won't work.

 try {
        insert dup1;
        System.assert(false);
     } catch (DmlException e) {
       ....
     }

That line is currently working as it's written. It does the insert, but since there is no error in the trigger, it continues to the next line which explicitly states to fail the assertion (because it shouldn't have gotten there). The execution path the test case is intending is that it will do the insert, which will throw an exception, skipping the assert and going in to the exception block.

You'll have to either uncomment the error code in the trigger or find some other way to throw an exception when a duplicate is detected from the trigger in order for this test to work.

The main problem is that without either of those, the trigger doesn't really do anything right now - it detects a duplicate but it doesn't try to stop it.

It sounds like what you want is some way to stop the insert from happening but without alerting the user. I'm not sure this is possible since it usually takes them to the lead's detail page after insert - where would it take them now? They'd probably also be confused if they tried to navigate back to that lead.

  • Yes - this scaled down version does nothing, no prob. – AMM Sep 6 '12 at 15:21
  • (sorry, didn't know C/R submitted).... As for error throwing.. can someone give an example of this? Or is it a huge ordeal? :-/ – AMM Sep 6 '12 at 15:22
  • here is the URL to the original code being ripped off: salesforce.com/docs/developer/cookbook/Content/apex_dedupe.htm – AMM Sep 6 '12 at 15:30
  • 1
    @AMM - the addError() call is documented here. I'm not sure why you're commenting it out. The test won't pass if the errors are not thrown. In fact, the test is working perfectly right now - it's telling you that the trigger is not preventing duplicates. – metadaddy Sep 6 '12 at 17:17
  • 2
    Yes - right now all the System.assert() calls in the test method will fail, since the trigger is not raising the expected error. You will need to rework the test method to match the changes to the trigger. – metadaddy Sep 6 '12 at 18:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.