You need to sign in to do that
Don't have an account?
Before Delete Trigger for Contact - Bulk Test Error
I've attempted to create a before delete trigger on the Contact object that will disallow deletion if an Activity (Event or Task) exists for that Contact. If there are no Activities, the Contact will be deleted, along with any associated Production Memberships (custom object). The trigger works on an individual basis using the UI, but I'm not returning the expected amount of rows after deletion in my test class. Unfortunately, I'm too green to know if the error lies in my trigger or my test. Any help would be appreciated. Thanks!
Here's my trigger:
trigger beforeContactDelete on Contact (before delete) { //Create Set of Contacts from trigger Set<ID> contactIDs = new Set<ID>(); for (Contact c : Trigger.old) { contactIDs.add(c.ID); } //All activities tied to a Contact in the trigger Set<ID> allActivities = new Set<ID>(); for (Event e : [SELECT WhoId FROM Event WHERE WhoId IN : contactIDs]) { allActivities.add(e.WhoId); } for (Task t : [SELECT WhoId FROM Task WHERE WhoId IN : contactIDs]) { allActivities.add(t.WhoId); } //All Contacts with activities Set<ID> dirtyContacts = new Set<ID>(); for (Contact c : [SELECT ID FROM Contact WHERE ID IN : allActivities]) { dirtyContacts.add(c.ID); } //Create set of Contacts from trigger without activities Set<ID> cleanContacts = new Set<ID>(); cleanContacts.addAll(contactIDs); cleanContacts.removeAll(dirtyContacts); //Create List of Production Memberships tied to a clean Contact List<Production_Member__c> productionMemberships = [SELECT ID FROM Production_Member__c WHERE Contact__c IN : cleanContacts]; //Delete the contact and the Production Member for (Contact c : Trigger.old) { if(Trigger.isBefore) { if(Trigger.isDelete) { if(dirtyContacts.containsAll(Trigger.oldMap.keySet())) { c.addError('This contact has an activity and therefore cannot be deleted'); } else if(cleanContacts.containsAll(Trigger.oldMap.keySet())) { if(productionMemberships != null) { delete productionMemberships; } } } } } }
Here's the test class:
@isTest private class testBeforeContactDelete { static testMethod void bulkContactDeleteTest() { //Create the list of contacts to test delete List<Contact> testContacts = [SELECT ID FROM Contact WHERE Account.Name = 'contactTest']; //Start Contact Delete Trigger Test.startTest(); delete testContacts; Test.stopTest(); //Check for desired results List<Contact> deletedContacts = [SELECT ID FROM Contact WHERE Account.Name = 'contactTest']; List<Production_Member__c> deletedPMs = [SELECT ID FROM Production_Member__c WHERE Contact__r.Account.Name = 'contactTest']; } }
I'd probably do something like the above. Note I'm just typing this into the editor, I'm sure it's not perfect. :-)
The theory behind the test classes is that they are data independent from the current state of an instance. So, somewhere in your test script I'd have expected to see code which did the following:
1. creates 5 Contacts
2. creates 1 task for Contact 1
3. creates 1 event for Contact 2
4. creates both a task and an event for Contact 3
5. creates production memberships for Contacts 4 and 5
6. creates production memberships for Contact 1 and 2
starttest
7. does a delete of all the contacts
stoptest
8. uses 3 system asserts to check that contact 1, 2 and 3 are still present.
system.assertEquals(1,[select count() from contact where id = :con[0].id); // example for one contact
9. check that contact 4 is gone.
10 check that production memberships that were linked to 4 and 5 are gone.
11 check that production memberships that were linked to 1and 2 are still present.
I hope this helps, best, Steve.
All Answers
I'd probably do something like the above. Note I'm just typing this into the editor, I'm sure it's not perfect. :-)
The theory behind the test classes is that they are data independent from the current state of an instance. So, somewhere in your test script I'd have expected to see code which did the following:
1. creates 5 Contacts
2. creates 1 task for Contact 1
3. creates 1 event for Contact 2
4. creates both a task and an event for Contact 3
5. creates production memberships for Contacts 4 and 5
6. creates production memberships for Contact 1 and 2
starttest
7. does a delete of all the contacts
stoptest
8. uses 3 system asserts to check that contact 1, 2 and 3 are still present.
system.assertEquals(1,[select count() from contact where id = :con[0].id); // example for one contact
9. check that contact 4 is gone.
10 check that production memberships that were linked to 4 and 5 are gone.
11 check that production memberships that were linked to 1and 2 are still present.
I hope this helps, best, Steve.
Hi Steve,
Thanks for your reply. I appreciate your test class explanation - I'll see what I can put together. As for your trigger recommendations, is there anything else that needs to be written to delete the appropriate contacts after adding the Contact IDs to the okToKill Set? I apologize if I'm assuming too much, I know you made your edits on the fly, but I remain confused as to where in the loop the Contact is being deleted.
Thanks for your continued help.
Never mind, I figured it out. Thanks agian.