Salesforce重复机会校验触发器的测试类编写求助
Fixing Your Opportunity Duplicate Prevention Trigger & Test Class
Let’s walk through refining your trigger for better performance and fixing up your test class to cover all critical scenarios.
First: Refine Your Trigger
Your original trigger has a couple of efficiency and logic alignment issues. Here’s an improved version that’s more scalable and matches your requirement to block non-admins from creating duplicate Opportunities (same account + type) within 90 days:
trigger leadDuplicatePreventer on Opportunity (before insert) { // Skip validation entirely if current user is a System Administrator Profile currentUserProfile = [SELECT Id, Name FROM Profile WHERE Id = :UserInfo.getProfileId() LIMIT 1]; if (currentUserProfile.Name == 'System Administrator') { return; } // Collect unique Trigger_Help__c values from the new Opportunities being inserted Set<String> newTriggerHelpValues = new Set<String>(); for (Opportunity opp : Trigger.new) { if (opp.Trigger_Help__c != null) { newTriggerHelpValues.add(opp.Trigger_Help__c); } } // Only query existing Opportunities that match the new values (avoids fetching all 90-day records) Set<String> existingDuplicateValues = new Set<String>(); for (Opportunity existingOpp : [ SELECT Trigger_Help__c FROM Opportunity WHERE Trigger_Help__c IN :newTriggerHelpValues AND CreatedDate = LAST_N_DAYS:90 ]) { existingDuplicateValues.add(existingOpp.Trigger_Help__c); } // Block insertion for duplicates for (Opportunity opp : Trigger.new) { if (existingDuplicateValues.contains(opp.Trigger_Help__c)) { opp.addError('An Opportunity of this type already exists on this Account. Please contact a system administrator with questions.'); } } }
Key Improvements:
- Skips validation immediately for admins (cleaner logic)
- Only queries existing Opportunities that match the new records’
Trigger_Help__cvalues (way more efficient for large orgs) - Avoids unnecessary data processing by focusing only on relevant records
Next: Complete Your Test Class
Your current test class is missing critical assertions and doesn’t test the admin user scenario. Here’s a full test class that covers both non-admin (blocked) and admin (allowed) cases:
@isTest private class TestleadDuplicatePreventer { // Test that non-admin users can't create duplicate Opportunities @isTest static void testNonAdminBlockedFromDuplicate() { // Create test Account Account testAcct = new Account(Name='Test Account'); insert testAcct; // Create first valid Opportunity Opportunity firstOpp = new Opportunity( Name = testAcct.Name + ' Initial Opportunity', StageName = 'Open Opportunity', CloseDate = System.today().addMonths(1), Oppty_Type__c = 'UCO Service', AccountId = testAcct.Id ); insert firstOpp; // Create a non-admin user to test with Profile nonAdminProfile = [SELECT Id FROM Profile WHERE Name != 'System Administrator' LIMIT 1]; User nonAdminUser = new User( Alias = 'testnonadmin', Email = 'nonadmin@testorg.com', EmailEncodingKey = 'UTF-8', LastName = 'NonAdmin', LanguageLocaleKey = 'en_US', LocaleSidKey = 'en_US', ProfileId = nonAdminProfile.Id, TimeZoneSidKey = 'America/Los_Angeles', Username = 'nonadmin@testorg.com' ); insert nonAdminUser; // Run the test as the non-admin user System.runAs(nonAdminUser) { // Attempt to create a duplicate Opportunity Opportunity duplicateOpp = new Opportunity( Name = 'Duplicate Opportunity', StageName = 'Open Opportunity', CloseDate = System.today().addMonths(2), Oppty_Type__c = 'UCO Service', AccountId = testAcct.Id ); // Verify insertion fails with the correct error Test.startTest(); Database.SaveResult saveResult = Database.insert(duplicateOpp, false); Test.stopTest(); System.assert(!saveResult.isSuccess(), 'Non-admin user should be blocked from creating duplicates'); System.assertEquals( 'An Opportunity of this type already exists on this Account. Please contact a system administrator with questions.', saveResult.getErrors()[0].getMessage(), 'Error message does not match expected text' ); } } // Test that admin users CAN create duplicate Opportunities @isTest static void testAdminAllowedToCreateDuplicate() { // Create test Account Account adminTestAcct = new Account(Name='Admin Test Account'); insert adminTestAcct; // Create first Opportunity Opportunity firstAdminOpp = new Opportunity( Name = adminTestAcct.Name + ' Initial Opportunity', StageName = 'Open Opportunity', CloseDate = System.today().addMonths(1), Oppty_Type__c = 'UCO Service', AccountId = adminTestAcct.Id ); insert firstAdminOpp; // Create an admin user to test with Profile adminProfile = [SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1]; User adminUser = new User( Alias = 'testadmin', Email = 'admin@testorg.com', EmailEncodingKey = 'UTF-8', LastName = 'Admin', LanguageLocaleKey = 'en_US', LocaleSidKey = 'en_US', ProfileId = adminProfile.Id, TimeZoneSidKey = 'America/Los_Angeles', Username = 'admin@testorg.com' ); insert adminUser; // Run the test as the admin user System.runAs(adminUser) { // Create a duplicate Opportunity Opportunity adminDuplicateOpp = new Opportunity( Name = 'Admin Duplicate Opportunity', StageName = 'Open Opportunity', CloseDate = System.today().addMonths(2), Oppty_Type__c = 'UCO Service', AccountId = adminTestAcct.Id ); // Verify insertion succeeds Test.startTest(); insert adminDuplicateOpp; Test.stopTest(); Opportunity insertedOpp = [SELECT Id FROM Opportunity WHERE Id = :adminDuplicateOpp.Id]; System.assertNotEquals(null, insertedOpp, 'Admin user should be allowed to create duplicates'); } } }
Key Test Class Fixes:
- Uses
System.runAs()to simulate both user types - Explicitly asserts success/failure outcomes instead of just catching exceptions
- Validates the exact error message is thrown for non-admins
- Avoids unnecessary SOQL queries by reusing the already inserted Account ID
内容的提问来源于stack exchange,提问作者KattheSpork
相关产品推荐
相关产品推荐

