+ Start a Discussion
mgodseymgodsey 

Unit Test for Extension Class for Custom Cloning

I have a VF page and Controller Extension that allows me to clone a custom object (ProposalFlight__c) record. The ProposalFlight__c record has a lookup field to another custom object, called Geo__c. Using the VF page (which overrides the custom clone button) and the Controller Extension, I am able to clone both ProposalFlight__c and Geo__c at the same time. However, I'm really struggling with creating the unit test for the controller extension.

 

VF Page:

<apex:page standardController="ProposalFlight__c" extensions="ProposalFlightCloneExtension" 
    action="{!cloneRecord}">
    <apex:pageMessages />
</apex:page>

 

Controller Extension (I've replaced the fields that are actually in the queury with (all Fields) just to make it reasier to read here):

 

public class ProposalFlightCloneExtension{
    
    //Variable to hold current record
     ProposalFlight__c currentRecord;
     
     //Standard constructor method
     public ProposalFlightCloneExtension(ApexPages.StandardController controller){
         currentRecord = (ProposalFlight__c)controller.getRecord();
     } 
     
      public PageReference cloneRecord(){
         //Variable to hold the new record
         ProposalFlight__c newRecord;
         Savepoint sp = Database.setSavepoint();
         
         try{
         
             //first clone the Geo Record
             Geo__c clonedGeo;
             
             for(Geo__c relatedGeo: [SELECT (All Fields) FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE id=: currentRecord.id)]){
                 Geo__c newGeo = relatedGeo.clone(false);
                 clonedGeo = newGeo;
             } 
             insert clonedGeo;
             
             //now clone the Proposal Flight
             currentRecord = [SELECT (All Fields) FROM ProposalFlight__c WHERE id=:currentRecord.id];
             newRecord = currentRecord.clone(false);
             newRecord.ApprovalStatus__c = Status.NotSubmitted;
             newRecord.ClonedFrom__c = currentRecord.id;
             newRecord.Geo__c = clonedGeo.ID;
             newRecord.GeoTargetSummary__c = clonedGeo.Text__c;
             insert newRecord;

         }catch(Exception e){
             Database.rollback(sp);
             ApexPages.addMessages(e);
             return null;
         }
         
         return new PageReference('/'+newRecord.id);
     }

}

 

 

My Unit Test so far:

 

@isTest (SeeAllData = True)
private class Test_ProposalFlightCloneExtension{
    
    static testMethod void testProposalFlightClone(){
    
        //create test data
        Account acct = UnitTestFactory.makeAccount();
        Opportunity opp = UnitTestFactory.makeMasterCPMOpp(acct.id);
        ProposalFlight__c pf = UnitTestFactory.makeCPMPF(opp.id);
        Geo__c geo = [SELECT Id FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE Id =: pf.Id)];
        
        //Go to Page
        Test.setCurrentPage(Page.ProposalFlightClone);
        
        //Set Parameters that would be passed in
        ApexPages.currentPage().getParameters().put('Id', pf.Id);
        
        //Instantiate a new controller with all parameters in place
        ProposalFlightCloneExtension ext = new ProposalFlightCloneExtension(new ApexPages.StandardController(pf));
        
        PageReference pageRef = Page.ProposalFlightClone;

    
    }

}

 The unit test passes, but is only covering 12% of the class. It doesn't cover any of the actual cloning logic. If anyone could point me in the right direction I would really appreciate it. Thank you!

 

Best Answer chosen by Admin (Salesforce Developers) 
crop1645crop1645

mgodsey 

 

You are almost there. Your testmethod needs to invoke the cloneRecord() method which presumably is invoked by your custom button. The testmethod has to simulate the button pushes by invoking the controller methods that the button's action is associated with

 

@isTest (SeeAllData = True)
private class Test_ProposalFlightCloneExtension{
    
    static testMethod void testProposalFlightClone(){
    
        //create test data
        Account acct = UnitTestFactory.makeAccount();
        Opportunity opp = UnitTestFactory.makeMasterCPMOpp(acct.id);
        ProposalFlight__c pf = UnitTestFactory.makeCPMPF(opp.id);
        Geo__c geo = [SELECT Id FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE Id =: pf.Id)];
        
        //Go to Page
        Test.setCurrentPage(Page.ProposalFlightClone);
        
        //Set Parameters that would be passed in
        ApexPages.currentPage().getParameters().put('Id', pf.Id);
        
        //Instantiate a new controller with all parameters in place
        ProposalFlightCloneExtension ext = new ProposalFlightCloneExtension(new ApexPages.StandardController(pf));
        
        PageReference pageRef = ext.cloneRecord();

    
    }

}

 Also, why does your testmethod need the @isTest(SeeAllData=true) annotation? This should be avoided when possible and you should rely on test data created by the testmethod

All Answers

crop1645crop1645

mgodsey 

 

You are almost there. Your testmethod needs to invoke the cloneRecord() method which presumably is invoked by your custom button. The testmethod has to simulate the button pushes by invoking the controller methods that the button's action is associated with

 

@isTest (SeeAllData = True)
private class Test_ProposalFlightCloneExtension{
    
    static testMethod void testProposalFlightClone(){
    
        //create test data
        Account acct = UnitTestFactory.makeAccount();
        Opportunity opp = UnitTestFactory.makeMasterCPMOpp(acct.id);
        ProposalFlight__c pf = UnitTestFactory.makeCPMPF(opp.id);
        Geo__c geo = [SELECT Id FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE Id =: pf.Id)];
        
        //Go to Page
        Test.setCurrentPage(Page.ProposalFlightClone);
        
        //Set Parameters that would be passed in
        ApexPages.currentPage().getParameters().put('Id', pf.Id);
        
        //Instantiate a new controller with all parameters in place
        ProposalFlightCloneExtension ext = new ProposalFlightCloneExtension(new ApexPages.StandardController(pf));
        
        PageReference pageRef = ext.cloneRecord();

    
    }

}

 Also, why does your testmethod need the @isTest(SeeAllData=true) annotation? This should be avoided when possible and you should rely on test data created by the testmethod

This was selected as the best answer
mgodseymgodsey

Thank you, that did the trick! I really appreciate the help and explanation.

 

I have to have See All Data = True, because when a Proposal Flight is created, through a trigger a product is automatically created. I was under the impression that inserting a pricebook entry for a product isn't feasible from a test since the standard pricebook isn't accessible and can't be created in a running test. Inserted a pricebook entry for a custom pricebook isn't supported since this requires defining a standard pricebook.

 

Feel free to correct me if I'm wrong about this! It would be great to get See All Data = True out of the unit tests if possible.