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
DahveedDahveed 

100% Test Coverage Code not deploying to production

I have written a trigger an handler with test code which works perfectly in my full config sandbox. However when I go to deploy to production I get errors which say it can't insert an opportunity line item.  Why would this work in the sandbox but throw this error in production? Can anyone help me? I've spent 2 days changing my code trying to get this work and it makes not sense. It seems it can't create a product line item.  I've added line numbers where the trouble is.

 

Run Failures:
  lineItemTriggerHandlerTester.testAddDeleteLineItems System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, opportunityLineItemTrigger: execution of AfterInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Class.lineItemTriggerHandler.conItemSet: line 55, column 1
Class.lineItemTriggerHandler.onAfterInsert: line 29, column 1
Trigger.opportunityLineItemTrigger: line 6, column 1: []

 

Here is my class, trigger, and test code.

 

trigger opportunityLineItemTrigger on OpportunityLineItem (after insert,before delete) {

    lineItemTriggerHandler handler = new lineItemTriggerHandler();
    
    if(Trigger.isInsert){
6        handler.OnAfterInsert(Trigger.new);
    }
    else if(Trigger.isDelete){
        handler.OnDelete(Trigger.old, Trigger.oldMap);
    }
    
}

 

public with sharing class lineItemTriggerHandler {

    public void onAfterInsert(List<OpportunityLineItem> newRecords){
        Map<ID,OpportunityLineItem> newMap = new Map<ID,OpportunityLineItem>();
            
        for(OpportunityLineItem oli : newRecords){
                            
                newmap.put(oli.id,oli);            
        }
        
        //Create a list of all product line items attached to the opportunity
        List<OpportunityLineItem> lineItemChk = [SELECT 
        Id, 
        OpportunityId,
        Opportunity.StageName, 
        Quantity,
        Discount,
        ListPrice,
        TotalPrice,
        Product_Family__c,
        Billing_Rate__c,
        PricebookEntry.Product2.Family        
        FROM OpportunityLineItem WHERE Id IN : newmap.keyset()];
        
        
                
        if(lineItemChk.size() > 0){
             Integer cCount = productFamilySet(lineItemChk);
29             conItemSet(lineItemChk,cCount);                
        }
    }
    /* Sets Product_Family__c on the opportunity product line item */
    // Receives list of opportunitylineitems
    // Returns an integer    
    private Integer productFamilySet(List<OpportunityLineItem> items){
        integer cCount = 0;
        for(OpportunityLineItem oli: items){
            If(oli.Product_Family__c == null){
                oli.Product_Family__c = oli.PricebookEntry.Product2.Family;
            }
            If(oli.Product_Family__c == 'Consulting'){
                cCount = cCount + 1;    
            }
        }
        update items;
        return cCount;
    }
    
    /* Sets the PLIConsultingCalc on the opportunity to the number type 'Consulting' line items */
    // receives a list of oppline items and integer of number of consulting items
    
    private void conItemSet(List<OpportunityLineItem> items,Integer pCount){            
        Opportunity opp = [SELECT Id, PLIConsultingCalc__c FROM Opportunity Where Id =: items[0].OpportunityId];
        
        If(opp.PLIConsultingCalc__c == null){
        	opp.PLIConsultingCalc__c = 0;
        }
55        opp.PLIConsultingCalc__c = opp.PLIConsultingCalc__c + pCount;
        update opp;
        
    }
         
    
    public void OnDelete(List<OpportunityLineItem> toDeleteRecords, Map<ID,OpportunityLineItem> oldMap){
        
        integer dCount = 0;
        
        if(toDeleteRecords.size() > 0){
            for(OpportunityLineItem doli: toDeleteRecords){
                if(doli.Product_Family__c == 'Consulting'){
                    dCount = dCount - 1;
                }
            }
            if(dCount < 0){
                Opportunity dOpp = [SELECT Id, PLIConsultingCalc__c FROM Opportunity WHERE Id =: toDeleteRecords[0].OpportunityId];
                dOpp.PLIConsultingCalc__c = dOpp.PLIConsultingCalc__c + dCount;
                update dOpp;
            }            
        }
    }
}

 

@isTest(seeAllData=true)
private class lineItemTriggerHandlerTester{

     static testMethod void testAddDeleteLineItems() {
// set up our data for each test method
        /* Create Account */
        Account a = new Account(Name='test123', CurrencyIsoCode='USD',BillingCountry = 'United States');
        insert a;
                   
        /* Get the standard pricebook. There must be a standard pricebook already in the target org.  */        
        Pricebook2 standardPB = [SELECT Id,IsStandard FROM Pricebook2 WHERE IsStandard=true];     
        System.AssertEquals(true , standardPB.IsStandard == true);
        
        /* Create and check Opportunity */
        date futureDay = date.today();
        futureDay = futureDay.addDays(2);
        Opportunity opp = new Opportunity(name='testOppInProduction1234', stagename='2 - Validation',Z_ASP_monthly_Y__c=10,CurrencyIsoCode = 'USD',Pricebook2Id=standardPB.Id, Z_Top_Feeling__c=50, CloseDate=futureDay,LeadSource='Client Referral',Account=a);
        insert opp;
        Opportunity oppChk = [SELECT Name FROM Opportunity WHERE Id = :opp.Id];
        System.assertEquals(opp.Name,oppChk.Name);
        
        /* Setup Products */
        Product2 p1 = new Product2(Name='FF - Functional Consultant', Family='Consulting',IsActive=true);
        insert p1;
        Product2 p1Chk = [SELECT Name FROM Product2 WHERE Id = :p1.Id];
        System.assertEquals(p1Chk.Id,p1.Id);
        
        /* Setup PriceBook Entry */
        PricebookEntry pbe1 = new PricebookEntry(Pricebook2Id=standardPB.Id, Product2Id=p1.Id, CurrencyIsoCode = 'USD', UnitPrice=10, isActive=true);
        insert pbe1;
        PricebookEntry pbe1Chk = [SELECT Pricebook2Id FROM PricebookEntry WHERE ID = :pbe1.Id];
        System.assertEquals(pbe1.Id,pbe1Chk.Id); 
        
        /* Setup OpportunityLIneItem Check Product Family And PLIConsulting */
        OpportunityLineItem oli = new OpportunityLineItem(PriceBookEntryId=pbe1.Id, OpportunityId=opp.Id, Quantity=1, UnitPrice=10);
        insert oli;
        OpportunityLineItem oliChk = [SELECT PriceBookEntryId,Product_Family__c FROM OpportunityLineItem WHERE Id = :oli.Id];
        System.assertEquals(pbe1.Id, oliChk.PriceBookEntryId);
        System.assertEquals('Consulting',oliChk.Product_Family__c);
        
        /* Check PLIConsultingCalc field */
        Opportunity pliChk = [SELECT Id, PLIConsultingCalc__c FROM Opportunity WHERE Id = :opp.Id];
        System.assertEquals(1, pliChk.PLIConsultingCalc__c);
        
        /* Delete Line Item */
        delete oli;
        Opportunity delPLIChk = [SELECT Id, PLIConsultingCalc__c FROM Opportunity WHERE Id = :opp.Id];
        System.assertEquals(0,delPLIChk.PLIConsultingCalc__c);       
    }    
}

 Thanks for any help!!

 

Dahveed

 

Best Answer chosen by Admin (Salesforce Developers) 
Bhawani SharmaBhawani Sharma
Add below line before line# 55
if(pCount == null) pCount = 0;

opp.PLIConsultingCalc__c = opp.PLIConsultingCalc__c + pCount;

All Answers

Bhawani SharmaBhawani Sharma
Add below line before line# 55
if(pCount == null) pCount = 0;

opp.PLIConsultingCalc__c = opp.PLIConsultingCalc__c + pCount;
This was selected as the best answer
DahveedDahveed

Wow that worked, but the reality is it shouldn't be null. It seems the test code isn't creating the Opportunity Line Item and that's why the pCount is getting passed null. Is that something funny when dealing with pricebooks in test code? Why would it give me full coverage and allow me to created line items no problem in my full config sandbox. I'm writing a more complex trigger on my product line items and will surely run into this again.

 

Thanks heaps!

 

Dahveed