function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Eager-2-LearnEager-2-Learn 

Testing Exception handlers

Hi,

 

I just can't seem to get code coverage for Exception handlers! 

 

Can someone please help me? 

 

Below are two code blocks.  The first one is the actual existing TEST script and the second is the controller with the two Exception handlers that never get code coverage which is causing me to only get 72% code coverage!

 

TEST SCRIPT:

private class TestOpportunityDeepCloneController {
    static testMethod void testOpportunityDeepCloneController_test1() {        
        Account testAcc1 = new Account();
        testAcc1.Name = 'Test Account1';
        insert testAcc1 ;
        
        Account testAcc2 = new Account();
        testAcc2.Name = 'Test Account2';
        insert testAcc2 ;
        
        Contact testContact = new  Contact();
        testContact.AccountId = testAcc2.id;
        testContact.FirstName = 'Test';
        testContact.LastName = 'Test'; 
        testContact.Phone = '555-555-5555';
        testContact.Email = 'OppDeepClone@test.com';
        insert testContact;        
        
        Opportunity testOpp = new Opportunity();
        Date closedDate = date.newinstance(2012, 1, 1);
        Date effectiveDate = date.newinstance(2012, 1, 2);
        
        testOpp.Name = 'Test Opportunity1';
        testOpp.AccountId = testAcc1.Id ;
        testOpp.StageName ='Proposal';
        testOpp.CloseDate = closedDate;
        testOpp.GeneralProducer__c = 'Direct';
        testOpp.Effective_Date__c = effectiveDate;
        insert testOpp ;
        
        PricebookEntry proceBookEntry = [ Select p.Name,  p.Id , p.IsActive From PricebookEntry p  where p.IsActive = true limit 1];
        
        OpportunityLineItem testOppProduct = new OpportunityLineItem();
        testOppProduct.OpportunityId = testOpp.id;
        testOppProduct.PricebookEntryId = proceBookEntry.Id;
        testOppProduct.Product_Sold__c = false;
        testOppProduct.Quantity = 10.00 ;
        testOppProduct.TotalPrice = 100.00;
        insert testOppProduct;
        
        Partner testPartner = new Partner();
        testPartner.AccountToId = testAcc2.id;
        testPartner.OpportunityId= testOpp.Id;
        testPartner.IsPrimary=true;        
        insert testPartner;
        
        OpportunityContactRole testConRole = new OpportunityContactRole();
        testConRole.OpportunityId = testOpp.id;
        testConRole.ContactId = testContact.id;        
        insert testConRole;
        
        ApexPages.StandardController sc = new ApexPages.StandardController(testOpp);
        OpportunityDeepCloneController  odcc = new OpportunityDeepCloneController(sc);
        
        
        Pagereference pageRef1 = Page.CloneOpportunityWithProduct ;
        pageRef1.getParameters().put('id', String.valueOf(testOpp.Id));
        pageRef1 = odcc.cloneWithProduct();
        
        System.assert(odcc.cloneWithProduct() != null);
        System.assert([select Id from Opportunity where Id=:odcc.newOpportunityId ].size() == 1);
        
        PageReference pageRef2 = Page.CloneOpportunityWithoutProduct ;
        pageRef2.getParameters().put('id', String.valueOf(testOpp.Id));
        pageRef2 = odcc.cloneWithoutProduct();
          
        System.assert(odcc.cloneWithoutProduct() != null);
        System.assert([select Id from Opportunity where Id=:odcc.newOpportunityId ].size() == 1);        
    }    
}

 

CONTROLLER:

public without sharing class OpportunityDeepCloneController {
    
    /* Instantiate  private /public valiables, properties */
    private ApexPages.StandardController controller { get; set; }
    private Opportunity opportunity { get; set; }
    public Id newOpportunityId { get; set; }
    OpportunityProcessorManager oppManager = new OpportunityProcessorManager();
    
    /* constructor */
    public OpportunityDeepCloneController(ApexPages.StandardController controller) {
            this.controller = controller;
            this.opportunity = (Opportunity)controller.getRecord();
    }

/*
* @purpose : The public method used to clone Opportunity with Product. This is called by the VF page 'CloneOpportunityWithProduct'
* @param :
* @return: PageReference  
*/
    public PageReference cloneWithProduct(){
        
         system.debug('Opportunity to be cloned with Product :' + opportunity);
         // setup the save point for rollback
         Savepoint sp = Database.setSavepoint();
         try{
            this.opportunity = QueryBase.getOpportunityById(opportunity.id);
            Opportunity newOpportunity = oppManager.cloneOpportunityWithProduct(opportunity);
            this.newOpportunityId = newOpportunity.id;
         }
         catch (Exception e){
            // roll everything back in case of errors
            Database.rollback(sp);
            ApexPages.addMessages(e);
            return null;
         }
        return new PageReference('/'+newOpportunityId );    
    }
 
/*
* @purpose : The public method used to clone Opportunity without Product. This is called by the VF page 'CloneOpportunityWithoutProduct'
* @param :
* @return: PageReference  
*/    
    public PageReference cloneWithoutProduct(){
        
        
         system.debug('Opportunity to be cloned without Product :' + opportunity);
         // setup the save point for rollback
         Savepoint sp = Database.setSavepoint();
         try{
            this.opportunity = QueryBase.getOpportunityById(opportunity.id);
            Opportunity newOpportunity = oppManager.cloneOpportunityWithoutProduct(opportunity);
            this.newOpportunityId = newOpportunity.id;
         }
         catch (Exception e){
            // roll everything back in case of errors
            Database.rollback(sp);
            ApexPages.addMessages(e);
            return null;
         }
        return new PageReference('/'+newOpportunityId );        
    }
}

 

 

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bvramkumarbvramkumar

You need to throw deliberate expections from functional code (not from test code) to cover the catch blocks....

 

Try this code just before your catch block.

if(Test.isRunningTest())
{
  integer x = 1/0;
}	

  

It worked for me.... 

All Answers

abhishektandon2abhishektandon2

Hi Try to raise exception in your test methd so that it will go to the Exception block

 

for example

 

Instaed os setting the Opportunity id in parameter, set any random string as ID in parameter, si that when your controller

serach for Opportunity for the ID

 

this.opportunity = QueryBase.getOpportunityById(opportunity.id);

 

this will raise an exception because no opportunity record will be found with that randon ID

 

 

 

 

 Pagereference pageRef1 = Page.CloneOpportunityWithProduct ;
        pageRef1.getParameters().put('id', String.valueOf(testOpp.Id));
        pageRef1 = odcc.cloneWithProduct();
Eager-2-LearnEager-2-Learn

I don't think that I follow!  Are you saying to add

 

this.opportunity = QueryBase.getOpportunityById(opportunity.id);

 

to the controller?  O perhaps I have a condition in the controller that test that a I am executing a test script and do the above line of code instead?

 

I appreciate your help.

craigmhcraigmh

Something like this should do it:

 

this.opportunity = QueryBase.getOpportunityById('ARandomStringThatIsNotAnId');

 

abhishektandon2abhishektandon2

No i am saying some thing like this

 

static testMethod void testOpportunityDeepCloneController_negative(){
ApexPages.StandardController sc = new ApexPages.StandardController(testOpp);
OpportunityDeepCloneController odcc = new OpportunityDeepCloneController(sc);


Pagereference pageRef1 = Page.CloneOpportunityWithProduct ;
pageRef1.getParameters().put('id', 'ABC12345');
pageRef1 = odcc.cloneWithProduct();
}

Eager-2-LearnEager-2-Learn

I actually tried that before submitting my question and it didn't work but being the doubting Thomas that I am I tried it again.

The code coverage still shows red (not covered) in the result list when I click on the 72%.

 

         catch (Exception e){
            // roll everything back in case of errors
            Database.rollback(sp);
            ApexPages.addMessages(e);
            return null;
         }



bvramkumarbvramkumar

You need to throw deliberate expections from functional code (not from test code) to cover the catch blocks....

 

Try this code just before your catch block.

if(Test.isRunningTest())
{
  integer x = 1/0;
}	

  

It worked for me.... 

This was selected as the best answer
Eager-2-LearnEager-2-Learn

Hi bvramkumar,

 

I will mark it as the correct solution but I wanted to discuss other concerns around this work around.

 

Because an error is forced for testing I had to comment out the assert statements because they check for data results and everything gets rolled back during an error!

 

I believe SF needs to address this some how so we can more easily test exceptions or dismiss exception handling from the code coverage requirements.

 

 

Thank you for this work around I now have 93% code coverage

 

craigmhcraigmh

Yeah, I agreed.

 

I have a static method that emails me with an exceptions that occur. My test class has a divide by zero piece of code to provide test coverage for this.

 

However, the catch statements in the controller are handled differently. They are a bit harder to test. I generally write code so that it won't ever hit the catch statement, then react to surprising behavior when it does. Either way, my classes are lengthy enough where not covering the catch statements doesn't bring the total number down that low, so I get by.

bvramkumarbvramkumar

The system asserts point is definitely of concern. May be for now we could some how logically manage this in test code...? SF will defintely not like to give the catch blocks an exceptional case so that it does not need to be covered. otherwise, the smart people around will write all their code in catch blocks just after throwing an exception from functional code... :) ... so they can get rid of test code... which is defintely not appreciable.

Eager-2-LearnEager-2-Learn

Valid points bvramkumar.  Thanks for the the feedback.

Roger WickiRoger Wicki
I've got some trouble getting my exception part tested. As far as I can read here, I could simply cause an error by dividing through zero, but that won't give me the desired type of error. I need to get a System.DMLException from an update operation. Because this update operation is in my handler class I can't simply add some error producing code there... Unless I do it the way with "isRunningTest" but that seems as if I'd produce code that is actually doing something wrong by purpose...