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
Jon GradmanJon Gradman 

Trigger code coverage, can't figure it out

Hi everyone,

For some reason I can't figure out how to get my test class code coverage to get above 65%. Can someone point me in the right direction?

Here is the trigger code:
trigger QuoteCharge_Update on zqu__QuoteRatePlanCharge__c ( after insert, after update )
{
// Step 1. Declare list to hold newly created opp line items.

List<OpportunityLineItem> listOli = new List<OpportunityLineItem>();

//Step 2. Loop through items in trigger for insert case: 
if (trigger.isInsert) {
  for(zqu__QuoteRatePlanCharge__c zQuoteCh1: Trigger.new) {
    OpportunityLineItem oli = new OpportunityLineItem();
    oli.OpportunityId = zQuoteCh1.Opportunity_Id__c;
    oli.Product2Id = zQuoteCh1.Product_Id__c;
    oli.Quote_Rate_Plan_Charge__c = zQuoteCh1.Id;
    oli.Quote_Rate_Plan__c = zQuoteCh1.zqu__QuoteRatePlan__c;
    oli.Description = zQuoteCh1.zqu__Description__c;
    oli.TotalPrice = zQuoteCh1.zqu__EffectivePrice__c;
    oli.Quantity = 1;
    oli.Quote_Amendment__c = Id.ValueOf(zQuoteCh1.Quote_Amendment_Id__c);
    if(zQuoteCh1.Projected_Product_MRR__c != null ) {
        oli.Projected_Product_MRR__c = zQuoteCh1.Projected_Product_MRR__c;
    }
    if(zQuoteCh1.Projected_Product_MRR__c == null) {
        oli.Projected_Product_MRR__c = zQuoteCh1.zqu__EffectivePrice__c;
    }
    
    
    listOli.add(oli);
    }
}
//Step 3. Loop through items in trigger for update case:
if(trigger.isUpdate) {
  for(zqu__QuoteRatePlanCharge__c zQuoteCh1: Trigger.new) {
    OpportunityLineItem oli = [SELECT id, Quote_Rate_Plan_Charge__c, Projected_Product_MRR__c, TotalPrice 
                                FROM OpportunityLineItem WHERE Quote_Rate_Plan_Charge__c = :zQuoteCh1.id];
    oli.TotalPrice = zQuoteCh1.zqu__EffectivePrice__c;
    if(zQuoteCh1.Projected_Product_MRR__c != null ) {
        oli.Projected_Product_MRR__c = zQuoteCh1.Projected_Product_MRR__c;
    }
    if(zQuoteCh1.Projected_Product_MRR__c == null) {
        oli.Projected_Product_MRR__c = zQuoteCh1.zqu__EffectivePrice__c;
    }

    listOli.add(oli);
    }
}

// Step 4 If any items in the list, insert into the db.
if(listOli.size() > 0 ) {
    upsert listOli;
}
}

Here is my test class (65% coverage):
@isTest
public class QuoteChargeTest
{
    static testMethod void QuoteChargeTest()
    {

        Account acct = new Account(name='dummy',Type='Prospect',Website='dummy.com',Account_Source__c='Sales',
                                  Priority__c=1);
        insert acct;
     
        Opportunity opp = new Opportunity(Name='dummy opp',Type='New Business',Product_Interest__c='Google PLA',
                                          Success_Notes__c='awesome',StageName='Discovery Set',CloseDate=System.today());
        insert opp;
        
        Product2 prod = new Product2(Name='PLA',Description='test text',isActive=true);
        insert prod;
        
        Pricebook2 book = new Pricebook2(Name='normal',isActive=true);
        insert book;
        
        Id standardPB = Test.getStandardPricebookId();
        
        PriceBookEntry dummy = new PriceBookEntry(isActive=true,Product2Id=prod.id,UnitPrice=1200,Pricebook2Id = standardPB);
        insert dummy;
        
        zqu__Quote__c newQuote = new zqu__Quote__c(zqu__Opportunity__c=opp.Id,zqu__Account__c=acct.Id,Name='test');
        insert newQuote;

        zqu__QuoteAmendment__c qa = new zqu__QuoteAmendment__c(Name='test amendment', zqu__Quote__c=newQuote.Id, zqu__Type__c='NewProduct');
        insert qa;
        
        zqu__ProductRatePlan__c prp = new zqu__ProductRatePlan__c(Name='test rateplan',zqu__Product__c=prod.Id);
        insert prp;
        
        zqu__ProductRatePlanCharge__c prpc = new zqu__ProductRatePlanCharge__c(Name='spend / or',zqu__Type__c='Usage',zqu__ListPrice__c=1);
        insert prpc;

        zqu__QuoteRatePlan__c qrp = new zqu__QuoteRatePlan__c(Name='qrp',zqu__ProductRatePlan__c=prp.Id,zqu__QuoteAmendment__c=qa.id,zqu__Quote__c=newQuote.Id,
                                                             zqu__AmendmentType__c='NewProduct');
        insert qrp;
        
        
    
            Test.starttest();
       try
           {
           zqu__QuoteRatePlanCharge__c qrpc = new zqu__QuoteRatePlanCharge__c(Name='Flat Fee',zqu__QuoteRatePlan__c=qrp.Id,zqu__Description__c='test',
                                                                           Projected_Product_MRR__c=500,zqu__EffectivePrice__c=1000);
           insert qrpc;
           zqu__QuoteRatePlanCharge__c qrpc2 = new zqu__QuoteRatePlanCharge__c(Name='Flat Fee',zqu__QuoteRatePlan__c=qrp.Id,zqu__Description__c='test',
                                                                           Projected_Product_MRR__c=500,zqu__EffectivePrice__c=1000);
     	  insert qrpc2;
           
           qrpc.Projected_Product_MRR__c = 0;
           update qrpc;
           
           
           }
           catch (DMLException e)
           {
          
           }
    Test.stoptest();
    }    
}

 
Andrew GAndrew G
Ok, first lets fix something in the trigger
if(trigger.isUpdate) {
	  	for(zqu__QuoteRatePlanCharge__c zQuoteCh1: Trigger.new) {
    		OpportunityLineItem oli = [SELECT id, Quote_Rate_Plan_Charge__c, Projected_Product_MRR__c, TotalPrice 
                                FROM OpportunityLineItem WHERE Quote_Rate_Plan_Charge__c = :zQuoteCh1.id];
A SELECT statement in a FOR loop is a No-No.  Not bulkified.
So:
if(trigger.isUpdate) {
		Set<Id> qprc_ids = new Set<Id>();
	  	for(zqu__QuoteRatePlanCharge__c zQuoteCh1: Trigger.new) {
	  		qprc_ids.add(zQuoteCh1.Id);
	  	}

   		List<OpportunityLineItem> listOLI = new List<OpportunityLineItem>();
   		listOLI = [SELECT id, Quote_Rate_Plan_Charge__c, Projected_Product_MRR__c, TotalPrice 
                                FROM OpportunityLineItem WHERE Quote_Rate_Plan_Charge__c in :qprc_ids];
//build a list of OLIs grouped by QRPC Id - a map of lists
		Map<Id,List<OpportunityLineItem>> mapOLIbyQRPC = new Map<Id,List<OpportunityLineItem>>();
		for(OpportunityLineItem oli : listOLI) {
        	if(mapOLIbyQRPC.containsKey(oli.Quote_Rate_Plan_Charge__c)) {
        		List<OpportunityLineItem> qrpcs = mapOLIbyQRPC.get(oli.Quote_Rate_Plan_Charge__c);
        		qrpcs.add(oli);
        		mapOLIbyQRPC.put(oli.Quote_Rate_Plan_Charge__c, qrpcs);
        	} else {
        		mapOLIbyQRPC.put(oli.Quote_Rate_Plan_Charge__c, new List<OpportunityLineItem>{oli})
        	}
        }
//now we have map, no need to have a query in the loop        
		List<OpportunityLineItem> workingOLI = new List<OpportunityLineItem>();
	  	for(zqu__QuoteRatePlanCharge__c zQuoteCh1: Trigger.new) {
			workingOLI = mapOLIbyQRPC.get(zQuoteCh1.Id);
			for( OpportunityLineItem oli : workingOLI ) {
				oli.TotalPrice = zQuoteCh1.zqu__EffectivePrice__c;
				//other code
			}
	  	}
	  	if(workingOLI.size() > 0 ) {
	  		update workingOLI;
	  	}
Note:  when using SELECT we should pass back to a list of records as you cannot be confident of the number of records returned by the query.

I note also that you use listOli.add(oli);  and upsert listOli;.  I'm not sure why as the code appears to pull the OLI from exists OLIs.  So the the list would contain the records (returned by the SELECT), so we simply update the record in the list and then use update list.

Next, the actual test class.
It appears OK in creating the test data, but there are not asserts, so we don't know if the code actually works. Try that as a test class.  The asserts will reassure you that the trigger is doing its thing and may help point you to where the missing code coverage is, for example not geting down a IF statement branch.
Test.starttest();
       	try
           {
           zqu__QuoteRatePlanCharge__c qrpc = new zqu__QuoteRatePlanCharge__c(Name='Flat Fee',zqu__QuoteRatePlan__c=qrp.Id,zqu__Description__c='test',
                                                                           Projected_Product_MRR__c=500,zqu__EffectivePrice__c=1000);
           insert qrpc;
           //get the oppty line items so we can test if the code works - coverage without asserts is useless
           List<OpportunityLineItem> insOLI = new List<OpportunityLineItem>();
           insOLI = [SELECT id, Quote_Rate_Plan_Charge__c, Projected_Product_MRR__c, TotalPrice 
                                FROM OpportunityLineItem WHERE Quote_Rate_Plan_Charge__c = :qrpc.id];

            System.assertEquals(insOLI[0].TotalPrice,qrpc.zqu__EffectivePrice__c);

           	qrpc.Projected_Product_MRR__c = 0;
           	update qrpc;
           //get the oppty line items so we can test if the code works - coverage without asserts is useless
           List<OpportunityLineItem> insOLI = new List<OpportunityLineItem>();
           insOLI = [SELECT id, Quote_Rate_Plan_Charge__c, Projected_Product_MRR__c, TotalPrice 
                                FROM OpportunityLineItem WHERE Quote_Rate_Plan_Charge__c = :qrpc.id];

            System.assertEquals(insOLI[0].Projected_Product_MRR__c ,qrpc.Projected_Product_MRR__c);

           }
           catch (DMLException e)
           {
          
           }
    Test.stoptest();
When you test your coverage, can you highlight what is not covered?  If, as I suspect, it is in the record update section, try grabbing the inserted test record again before doing the field change and record update.  Something like:
System.assertEquals(insOLI[0].TotalPrice,qrpc.zqu__EffectivePrice__c);
            qrpc = [SELECT Id, Projected_Product_MRR__c FROM zqu__QuoteRatePlanCharge__c WHERE Name="Flat Fee" ];

           	qrpc.Projected_Product_MRR__c = 0;
           	update qrpc;
*** caveat *** I have not tested the above code as my object structure does not include the custom objects in your environment.

Regards
Andrew