+ Start a Discussion
MikeGillMikeGill 

Testing try catch exceptions

Frustrated more than stuck. I want to add more exception handling, but end up just leaving out as I can never get full coverage on the code

 

How can I test try catch exceptions like the example below. Seems impossible to get coverage on the exception part of the try catch.

 

 

public with sharing class OpportunityTriggerHandler {
	
	/**
	*	@client			XYZ.
	*	@description	Basic account category update from opportunity to assist with writing classes
	*/
	    
    public OpportunityTriggerHandler(){}
    
    public void OnAfterUpdate(Opportunity[] oldOpp, Opportunity[] updatedOpp, Map<ID, Opportunity> oppMap){
    	
        Set<Id> accIds = new Set<Id>();
        Map<Id, String> catMap = new Map<Id, String>();
        
        for (Opportunity opp:[select Id,  OwnerId, AccountId, Category__c from Opportunity where Id in: oppMap.keySet()]){
        	accIds.add(opp.AccountId);
        	catMap.put(opp.AccountId, opp.Category__c);
        }
        
         List<Account> accToUpdate = new List<Account>();
    	  
    	  for (Account acc:[select Id, Display__c, Broadcast__c, Projector__c from Account where Id in: accIds]){
    	  	
    	  		String oppCat = catMap.get(acc.Id);
    	  	
    	  		
    	  		if (!acc.Projector__c &&  oppCat == 'Projector'){
    	  			acc.Projector__c = true;
    	  		}
    	  		
    	  		if (!acc.Display__c &&  oppCat == 'Display'){
    	  			acc.Display__c = true;
    	  		}
    	  		
    	  	accToUpdate.add(acc);
    	  }
    	  
		try{
    	  	update accToUpdate;
		}
		
		catch (Exception e){
			// Can't test this part
		}
       
     
    	
    }
    
   

}

 

Test class

@isTest
private class TestOpportunity {
	
	
	public static List<Account> accs;
	public static List<Opportunity> opps;
	public static List<Opportunity> oppsToTest;
	
	// Create static test data
	
	public static void init(){
		TestUtil testUtil = new TestUtil();
    	testUtil.createTestUsers(); 
       	testUtil.createTestAccounts();
    	testUtil.createTestOpps();
    	
    	accs = testUtil.accs;
    	opps = testUtil.opps;
	}

	// Test Projector
    static testMethod void myUnitTest_Projector() {
    	
    	init();
    	test.startTest();

    	oppsToTest = new List<Opportunity>();
   	
    	for (Opportunity opp:opps){
    		opp.Category__c = 'Projector';
    		System.assertEquals(opp.Account.Projector__c, false);
    		oppsToTest.add(opp);
    	}
	
    	update oppsToTest;

		// Requery updated account records to assert
		List<Account> accounts = [select Projector__c from Account where Id =: oppsToTest[0].AccountId];
		
		System.assertEquals(accounts[0].Projector__c, true);
		    		
    	test.stopTest();
        
        
    }
    
    // Test Display
     static testMethod void myUnitTest_Display() {
    	
    	init();
    	test.startTest();

    	oppsToTest = new List<Opportunity>();
   	
    	for (Opportunity opp:opps){
    		opp.Category__c = 'Display';
    		System.assertEquals(opp.Account.Display__c, false);
    		oppsToTest.add(opp);
    	}
	
    	update oppsToTest;

		// Requery updated account records to assert
		List<Account> accounts = [select Display__c from Account where Id =: oppsToTest[0].AccountId];
		
		System.assertEquals(accounts[0].Display__c, true);
		    		
    	test.stopTest();
        
        
    }
    
    // Test Exception
    
         static testMethod void myUnitTest_Exception() {
    	
    	// Force exception - how do I force an exception to be thrown
    	init();
    	test.startTest();
    	
    	oppsToTest = new List<Opportunity>();
   	
    	for (Opportunity opp:opps){
    		opp.Category__c = 'Display';
    		System.assertEquals(opp.Account.Display__c, false);
    		oppsToTest.add(opp);
    	}
	
    	update oppsToTest;
			
		    		
    	test.stopTest();
        
        
    }
    
    
    
}

 

Thanks

Navatar_DbSupNavatar_DbSup

Hi,
Use the below code inside the test method:
static testMethod void myUnitTest_Exception2()
{
Opportunity opp = new Opportunity(CloseDate = System.Today(), Name = 'TRN-0100438691', StageName = 'Pending');
insert opp;
opp.id='test';
update opp;
}

MikeGillMikeGill

Thanks

 

opp.id is not writable and therefore cannot save the test method.

 

Any more ideas?

BritishBoyinDCBritishBoyinDC

I hit this problem a lot as well...sometimes, you can force a failure by creating a record, referencing it, and then deleting it before you execute the  action that triggers the test, so forcing the test to fail, but I don't see that option here

 

I would suggest that you keep the try statement, and just live with the 90% coverage...so that if someone writes a validation rule in the future that makes your update fail, it will fail gracefully...

 

One other comment - I think you can streamline your code a bit...without seeing the trigger, I can 't be sure, but if oppMap is the newMap from the trigger, then where you have this:

 

public with sharing class OpportunityTriggerHandler {
	
	/**
	*	@client			XYZ.
	*	@description	Basic account category update from opportunity to assist with writing classes
	*/
	    
    public OpportunityTriggerHandler(){}
    
    public void OnAfterUpdate(Opportunity[] oldOpp, Opportunity[] updatedOpp, Map<ID, Opportunity> oppMap){
    	
        Set<Id> accIds = new Set<Id>();
        Map<Id, String> catMap = new Map<Id, String>();
        
        for (Opportunity opp:[select Id,  OwnerId, AccountId, Category__c from Opportunity where Id in: oppMap.keySet()]){
        	accIds.add(opp.AccountId);
        	catMap.put(opp.AccountId, opp.Category__c);
        }
        
         List<Account> accToUpdate = new List<Account>();
    	  
    	  for (Account acc:[select Id, Display__c, Broadcast__c, Projector__c from Account where Id in: accIds]){
    	  	
    	  		String oppCat = catMap.get(acc.Id);
    	  	
    	  		
    	  		if (!acc.Projector__c &&  oppCat == 'Projector'){
    	  			acc.Projector__c = true;
    	  		}
    	  		
    	  		if (!acc.Display__c &&  oppCat == 'Display'){
    	  			acc.Display__c = true;
    	  		}
    	  		
    	  	accToUpdate.add(acc);
    	  }
    	  
		try{
    	  	update accToUpdate;
		}
		
		catch (Exception e){
			// Can't test this part
		}
       
     
    	
    }
    
   

}

 

You can just write this:

public with sharing class OpportunityTriggerHandler {
	
	/**
	*	@client			XYZ.
	*	@description	Basic account category update from opportunity to assist with writing classes
	*/
	    
    public OpportunityTriggerHandler(){}
    
    public void OnAfterUpdate(Opportunity[] oldOpp, Opportunity[] updatedOpp, Map<ID, Opportunity> oppMap){
    	
        Set<Id> accIds = new Set<Id>();
        Map<Id, String> catMap = new Map<Id, String>();
        
//if oppMap is the newmap, it already has the values from the trigger
        for (Opportunity opp: oppMap.values () ){
        	//And you're storing AccountId twice...you can just use the map as a keyset I think
                //accIds.add(opp.AccountId);
        	catMap.put(opp.AccountId, opp.Category__c);
        }
        
         List<Account> accToUpdate = new List<Account>();
    	  
    	  for (Account acc:[select Id, Display__c, Broadcast__c, Projector__c from Account where Id in: catMap.keyset()]){
    	  	
    	  		String oppCat = catMap.get(acc.Id);
    	  	
    	  		
    	  		if (!acc.Projector__c &&  oppCat == 'Projector'){
    	  			acc.Projector__c = true;
    	  		}
    	  		
    	  		if (!acc.Display__c &&  oppCat == 'Display'){
    	  			acc.Display__c = true;
    	  		}
    	  		
    	  	accToUpdate.add(acc);
    	  }
    	  
		try{
    	  	update accToUpdate;
		}
		
		catch (Exception e){
			// Can't test this part
		}
       
     
    	
    }
    
   

}

 

 

MikeGillMikeGill

Always looking for ways to streamline things. You're correct oppMap is Trigger.newMap. Thanks for the pointer. 

 

The code checks out at 94% which is above the recommended 90%. Still anonying.

 

Thank you for responding.

 

Mike