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
Jonathan Osgood 3Jonathan Osgood 3 

Test Coverage for Clone Method

Hi All,

I'm a bit rusty on writing apex test code. I have a trigger that uses the .clone method to clone an opportunity and child records. Simply creating and inserting objects is not enough to test the trigger. I've tried Systems asserts to compare old opportuntiy to the new with no luck. Any advice on the best approach here?  

My trigger code (I realize I still need to pull the logic into a separate class and call that in my trigger) :  
 
trigger OpportunityTrigger on Opportunity (after insert, after update) {
    if(checkRecursive.runOnce()){
        
        
        
        
        // Interate selected opp records
        for (Opportunity opp : Trigger.new){
            if(opp.Renewable__c=='Yes' && opp.StageName=='Closed Won'){
                
                try{
                    id OpportunityId = opp.id;
                    List<Opportunity> oldOpps = [Select Accelera__c,renewable__c,RenewalCreated__c,jsImpacts__Added_from_Data_com__c,ASI_Opportunities__c,ASI_Strength__c,
                                                 ASI_Threats__c,ASI_Weakness__c,vs_Associated_eValuePrompter__c,Base_Number__c,Base_Term__c,BD_Opp__c,Big_Deal_Approved__c,vs_Business_Issue__c,vs_Business_Value__c,Capture_Opp__c,Close_Month_Try__c,Competition_Type__c,Contracting_Officer__c,Contrat_Type__c,Contract_Vehicle__c,CurrentGenerators__c,DB_Competitor__c,DealReg_Info__c,Deal_Registration_Date__c,Delivered_Services_Cost__c,Delivered_Services_Margin__c,Delivered_Services_Revenue__c,DeliveryInstallationStatus__c,Demos_Orals_BAFO__c,Differentiators__c,Discriminators__c,DRFP_RFP_Release_Date__c,Finance_Processed__c,Forecast_Category__c,Historical_Metric_1_Margin__c,Historical_Metric_2_Margin__c,Historical_Metric_3_Margin__c,Historical_Rev__c,Important_Qs_Updates_for_Opps__c,Incumbent__c,Industry_Date__c,Inside_Sales_Rep__c,Internal_Contract_Id__c,Is_Deal_Registered__c,vs_Last_Modified_eValuePrompter__c,Lowest_Line_Item_Margin__c,MainCompetitors__c,vs_Manager_Accepted__c,vs_Manager_Notes__c,
                                                 vs_Manager_Review_Request__c,Metric_1__c,Metric_2__c,Metric_3__c,Metric_4__c,MicrosoftRevenue__c,MiscRevenue__c,Mitigation__c,MSA__c,NAICS__c,NDA__c,NEW_Total_Quote_Margin_Value__c,Non_Commissionable__c,Notes_for_Processing_Order__c,Opportunity_Contains__c,Opportunity_ID__c,Option_Renewal_Period__c,Options_Number__c,Owner__c,Owner_Split_Percent__c,Partner_Commission__c,Period_of_Performance__c,TO_PoP_End__c,TO_PoP_Start__c,vs_Personal_Value__c,PM_Approach__c,PM_Assigned__c,PMO_Managed__c,Potential_Competitors__c,Pricing_Strategy__c,Prime__c,Prime_Contractor__c,vs_Problems__c,Process_Status_Valid_Since__c,ProductRevenue__c,Program_Summary__c,Project_Close_Date__c,Project_Number__c,Proposal_Lead__c,Latest_News__c,PWin__c,QB_SAP_SO__c,QuoteRenewalMargin__c,Reason_For_Stage__c,Reason_For_Stage_Notes__c,Renewable_Term__c,RenewalRevenue__c,RFI_Source__c,RFP_Opp_ID__c,RFP_Date__c,RFP_Status__c,Sales_Partner__c,SAP_Opportunity_ID__c,Service_Business_Opp_Type__c,Service_Contract_Type__c,Services_Invoiced_Through_Date__c,ServicesRevenue__c,SNACKsLead__c,vs_Solutions__c,
                                                 Solution_Type__c,SOW_Needed__c,Split_Rep__c,Split_Rep_Percent__c,Stage_Since_Date__c,Sub__c,Subcontractor__c,TCV__c,Technology_Approach__c,Total_Cloud_Margin__c,Total_Cloud_Revenue__c,Total_Enterprise_Services_Margin__c,Total_Enterprise_Services_Revenue__c,Total_Historical_Margin__c,Total_Managed_Services_Margin__c,Total_Managed_Services_Revenue__c,Total_Opportunity_Margin__c,Total_Opportunity_Revenue__c,Total_Product_Margin__c,Total_Product_Quantity__c,Total_Product_Revenue__c,TotalQuoteMargin__c,Total_Rebate_Margin__c,Total_Rebate_Revenue__c,TotalRevenue__c,
                                                 Total_Services_Margin__c,Total_Services_Revenue__c,Total_Workplace_Margin__c,Total_Workplace_Revenue__c,TrackingNumber__c,Value_Proposition__c,vs_Influencer_Role__c,vs_Vision_Match__c,Weighted_Opp_Margin__c,Weighted_Total_Margin__c,Workplace_Margin__c,AccountID,Amount,CloseDate,ContractID,CreatedByID,Description,ExpectedRevenue,ForecastCategoryName,LeadSource,NextStep,Name,OwnerID,RecordTypeID,Pricebook2ID,CampaignID,IsPrivate,Probability,TotalOpportunityQuantity,StageName,SyncedQuoteID,Type,
                                                 (Select OpportunityID,ID,Accelera_Sales_Rep__c,AccountID,AdditionalAddress,AdditionalName,AlternativeProjectManagerRate__c,ASI_Rep__c,ASI_Rep_E_Mail__c,BillingAddress,BillingName,ContactID,ContractID,ContractVehicle__c,CreatedByID,CustomProjectManagerHours__c,DefaultProjectManagerRate__c,Description,Discount,Email,EngineeringServicesDescription__c,ExpirationDate,Fax,For_End_User_del__c,GrandTotal,Internal_Comments__c,IsSyncing,Labor_Category__c,LaborDiscountPercent__c,LastModifiedByID,Name,Payment_Term__c,Payment_Terms__c,Phone,Project_Management_Hours__c,Project_Management_Rate__c,ProjectManagerActualCost__c,ProjectManagerPercentHours__c,Quote_Shipping_Handling__c,Quote_Tax__c,QuoteToAddress,QuoteToName,RecordTypeID,ShippingAddress,ShippingHandling,ShippingName,Status,Tax,TotalLaborActualCost__c,TotalLaborSalesPrice__c,TotalMicrosoftActualCost__c,TotalMicrosoftSalesPrice__c,TotalMiscActualCost__c,TotalMiscSalesPrice__c,TotalProductActualCost__c,TotalProductSalesPrice__c,TotalRenewalActualCost__c,TotalRenewalSalesPrice__c,Wrokplace__c from Quotes),
                                                 (Select PricebookEntryId,CreatedByID,ServiceDate,Discount,LastModifiedByID,Description,ListPrice,OpportunityID,Product2ID,ProductCode,Quantity,UnitPrice,Subtotal,Actual_Cost__c,Item_Margin__c,Quosal_Business_Unit__c,Quosal_Contract_Vehicle__c
                                                  from OpportunityLineItems) from Opportunity where ID = :OpportunityId AND RenewalCreated__c =False];
                    
                    if(oldOpps.size()>0){
                        List<OpportunityLineItem> olis = new List<OpportunityLineItem>();
                        List<Quote> qteList = new List<Quote>();
                        Opportunity oldOpp = oldOpps[0];
                        Opportunity newOpp = oldOpp.clone(false,true,false,false);
                        newOpp.StageName = 'Qualification';
                        newOpp.Name = oldOpp.Name + ' - RENEWAL';
                        integer months = integer.valueOf(oldOpp.Renewable_Term__c);
                        date newCloseDate = oldOpp.CloseDate;
                        newCloseDate = NewCloseDate.addMonths(months);
                        newOpp.CloseDate = newCloseDate;
                        newOpp.Reason_For_Stage__c = null;
                        newOpp.Probability = 5;
                        NewOpp.RenewalCreated__c = True;
                        OldOpp.RenewalCreated__c = True;
                        insert newOpp;
                        update oldOpp;
                        for(OpportunityLineItem oli : oldOpp.OpportunityLineItems){
                            
                            OpportunityLineItem oliNew = oli.clone(false,true,false,false);
                            oliNew.OpportunityId = newOpp.id;
                            
                            olis.add(oliNew);
                        }
                        for(Quote qte : oldOpp.quotes){
                            
                            quote qteNew = qte.clone(false,true,false,false);
                            qteNew.OpportunityId = newOpp.id;
                            
                            qteList.add(qteNew);
                        }
                        
                        if(olis.size() > 0)
                            insert olis;
                        if(qteList.size() > 0)
                            insert qteList;
                    }
                } catch (Exception e){            
                            system.debug(e.getMessage() + e.getStackTraceString()); 
                            
                        }
                    
                }
                
            }
        }
    }

My Test Code: 
@isTest
public class OpportunityCloneTriggerTest {
    
   @isTest
    public static void TestMethod1(){
        
        //Create Account
        Account newAccount = new Account(
            Name='TestAccount',
            Phone='3035551212');
        insert newAccount;
        
        //Create Product
        Product2 newProduct = new Product2(
            Name='NewProd',
            ProductCode = 'VSC24B100',
            isActive = true);
        insert newProduct;
        
        
        //Create your pricebook entry
        Id pricebookId = Test.getStandardPricebookId();
        PricebookEntry newPBE = new PricebookEntry(
            Pricebook2Id = pricebookId,
            Product2Id = newProduct.Id,
            UnitPrice = 500.00,
            IsActive = true
        );
        insert newPBE;
        
        //Create Opportunity
        Opportunity newOpportunity = new Opportunity(
            Name='NewOpp', 
            AccountId = newAccount.Id,
            StageName='Payment Processing',
            CloseDate=date.newInstance(2016, 1, 1));
        insert newOpportunity;
        
        
        //Validate single insert
        for(Opportunity o:[SELECT id FROM Opportunity 
                           WHERE id = :newOpportunity.id]) {
             System.assertEquals(o.id, newOpportunity.id);
            }
        
        
        
        //Create Opportunity Product
        OpportunityLineItem newOppLineItem = new OpportunityLineItem(
            OpportunityId = newOpportunity.Id, 
            PricebookEntryId = newPBE.Id,Quantity = 1, 
            TotalPrice = newPBE.UnitPrice
            );
       
            insert newOppLineItem;  
        
        
        //Create Opportunity Quote
        Quote newQuote = new Quote(
            name = 'testquote',
            OpportunityId = newOpportunity.Id, 
            ExpirationDate = date.newInstance(2016, 1, 1)
            );
        insert newQuote;
        
        //Update the stage
        newOpportunity.StageName='Closed Won';
        update newOpportunity;
    }
}

Lines not covered:

User-added image

User-added image
 
Amit Chaudhary 8Amit Chaudhary 8
You need to set "Renewable__c" ='Yes' in your test class. Like below
@isTest
public class OpportunityCloneTriggerTest {
    
   @isTest
    public static void TestMethod1(){
        
        //Create Account
        Account newAccount = new Account(
            Name='TestAccount',
            Phone='3035551212');
        insert newAccount;
        
        //Create Product
        Product2 newProduct = new Product2(
            Name='NewProd',
            ProductCode = 'VSC24B100',
            isActive = true);
        insert newProduct;
        
        
        //Create your pricebook entry
        Id pricebookId = Test.getStandardPricebookId();
        PricebookEntry newPBE = new PricebookEntry(
            Pricebook2Id = pricebookId,
            Product2Id = newProduct.Id,
            UnitPrice = 500.00,
            IsActive = true
        );
        insert newPBE;
        
        //Create Opportunity
        Opportunity newOpportunity = new Opportunity(
            Name='NewOpp', 
            AccountId = newAccount.Id,
            StageName='Payment Processing',
            CloseDate=date.newInstance(2016, 1, 1));
        insert newOpportunity;
        
        
        //Validate single insert
        for(Opportunity o:[SELECT id FROM Opportunity 
                           WHERE id = :newOpportunity.id]) {
             System.assertEquals(o.id, newOpportunity.id);
            }
        
        
        
        //Create Opportunity Product
        OpportunityLineItem newOppLineItem = new OpportunityLineItem(
            OpportunityId = newOpportunity.Id, 
            PricebookEntryId = newPBE.Id,Quantity = 1, 
            TotalPrice = newPBE.UnitPrice
            );
       
            insert newOppLineItem;  
        
        
        //Create Opportunity Quote
        Quote newQuote = new Quote(
            name = 'testquote',
            OpportunityId = newOpportunity.Id, 
            ExpirationDate = date.newInstance(2016, 1, 1)
            );
        insert newQuote;
        
        //Update the stage
		newOpportunity.Renewable__c = 'Yes';
        newOpportunity.StageName='Closed Won';
        update newOpportunity;
    }
}

Let us know if this will help you
 
Jonathan Osgood 3Jonathan Osgood 3
Thanks Amit. Unfortunately, that did not change the coverage %
Amit Chaudhary 8Amit Chaudhary 8
Can you please share checkRecursive class. You need to same class.

NOTE:- We need to set variable so that trigger will execute again once you will update opportunity