You need to sign in to do that
Don't have an account?

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 ); } }
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.
It worked for me....
All Answers
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 will raise an exception because no opportunity record will be found with that randon ID
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.
Something like this should do it:
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();
}
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%.
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.
It worked for me....
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
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.
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.
Valid points bvramkumar. Thanks for the the feedback.