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
jladdersjladders 

Trigger/Unit Test Help

Any help/idea will be more than appreciated! I have a trigger that inserts a new opportunity record once stage is set to closedwon, it works fine until i try to set the newly inserted record to closewon. I get the following error message
 
System.NullPointerException: Attempt to de-reference a null object: Trigger.RenewalOpportunity: line 9, column 48
 
contract_length__c is a number field while contract_activation_date is a date field. below is the code I have so far
 
Trigger
Code:
trigger RenewalOpportunity on Opportunity (after update) {
                        
    for (Integer i = 0; i < Trigger.new.size(); i++) {
               
       if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false && Trigger.new[i].RenewalOpportunity__c == null) {
            
            Opportunity renewalOpp = Trigger.new[i].clone(false);

            Double x = Trigger.old[i].Contract_Length__c;
            Integer y = x.intValue();
            
            renewalOpp.Name = 'Renewal - '+  Trigger.old[i].Name;
            renewalOpp.closedate = Trigger.old[i].Contract_Activation_Date__c.addmonths(y);
            renewalOpp.stagename = '0 - Very Early Stage';
            renewalOpp.probability = 0;
            renewalOpp.ForecastCategoryName = 'Pipeline';
            renewalOpp.Contract_Activation_Date__c = null;
            renewalOpp.Contract_Length__c = null;


            insert renewalOpp;
            
      if (Trigger.old[i].Name.startsWith('Renewal - ')) {
          renewalOpp.Name = Trigger.old[i].Name;
          update renewalOpp;
          }

      if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false && Trigger.new[i].RenewalOpportunity__c == null) {
            Opportunity newOpp = [select ID from Opportunity where id = :Trigger.new[i].ID];
            newOpp.RenewalOpportunity__c = renewalOpp.ID;
            update newOpp;
            }            
      }
   }
}

 
Unit Test
 
Code:
public class CreateOpportunity {

    static testMethod void testCreateOpportunityRenewal(){
    // Test opportunities moving from isWon = false to isWon = true
    try {
        
        Double Contract_Length = 13;
        Double x = Contract_Length;
        Integer y = x.intValue();
        
        Date today = System.today();
        Date contract_activation_date = System.today();
        Date closeDate = contract_activation_date.addmonths(y);
                 
        Opportunity opportunity = new Opportunity();
        
        opportunity.name = 'old opportunity name';
        opportunity.Contract_Length__c = 13;
        opportunity.contract_activation_date__c = today;
        opportunity.closedate = today;
        opportunity.stagename = 'Closed Lost';
        opportunity.probability = 1;
        opportunity.ForecastCategoryName = 'Closed';
                
        insert opportunity;
        
        System.assertEquals(opportunity.name, 'old opportunity name');

        opportunity.stagename = 'Closed Won';
        update opportunity;
        
        Opportunity updatedOpportunity = [select ID,RenewalOpportunity__c from Opportunity where id = :opportunity.ID];
        
        // go get new opportunity
        System.debug('opportunityId: ' + updatedOpportunity.RenewalOpportunity__c);
        Opportunity newOpportunity = [select ID, Name, Contract_Length__c, contract_activation_date__c, closedate, stagename, probability, forecastCategoryName from Opportunity where id = :updatedOpportunity.RenewalOpportunity__c];
        
        System.assertNotEquals(newOpportunity, null);
        
        System.assertEquals(newOpportunity.name, 'Renewal - old opportunity name');
        System.assertEquals(newOpportunity.Contract_Length__c, 12);        
        System.assertEquals(newOpportunity.contract_activation_date__c, today);
        System.assertEquals(newOpportunity.closedate, closeDate);
        System.assertEquals(newOpportunity.stagename, '0 - Very Early Stage');
        System.assertEquals(newOpportunity.probability, 0);
        System.assertEquals(newOpportunity.ForecastCategoryName, 'Pipeline');
        
        delete opportunity;
    }    
    catch (DmlException e) {
        System.assert(false);
    }

    // Test opportunities moving from isWon = false to isWon = false
    try {

        Double Contract_Length = 13;
        Double x = Contract_Length;
        Integer y = x.intValue();
        
        Date today = System.today();
        Date contract_activation_date = System.today();
        Date closeDate = contract_activation_date.addmonths(y);
            
        Opportunity opportunity = new Opportunity();
        opportunity.Contract_Length__c = 13;
        opportunity.contract_activation_date__c = today;
        opportunity.name = 'old opportunity name';
        opportunity.closedate = today;
        opportunity.stagename = 'Closed Lost';
        opportunity.probability = 1;
        opportunity.ForecastCategoryName = 'Closed';

        insert opportunity;
        
        System.assertEquals(opportunity.name, 'old opportunity name');
        
        opportunity.stagename = 'Final Steps';
        update opportunity;
        
        Opportunity updatedOpportunity = [select ID,RenewalOpportunity__c from Opportunity where id = :opportunity.ID];
        try
        {
            Opportunity newOpportunity = [select ID from Opportunity where id = :updatedOpportunity.RenewalOpportunity__c];
            System.assert(false);
        }
        catch (Exception e) {
        }
    
        delete opportunity;
    }    
    catch (DmlException e) {
        System.assert(false);
    }
  }
}

 
Thanks in adavance :)
Shadow8002Shadow8002
Hi,

I have faced issues similar to this before. I read through the code and i do not find anything obvious. There could be the possibility that the trigger is getting executed recursively.

Can you try using before Update?
jladdersjladders
I need the trigger to be fired after an opportunity as been updated that's why I used an after update.
kathyanikathyani
Line 9: do a system.debug. I got this error also for one of my unit tests and when I did a system.debug, the value was null in that variable.
It was not getting the value from the trigger.

I am not sure if this could be the reason but at least the exception was gone.
RTHawkRTHawk
Have you found a solution for this yet?
I am getting the same error in a very similar instance:

 trigger ICTrigger on Contact (after update) {
for (Integer i = 0; i < Trigger.new.size(); i++) {
if (Trigger.old[i].CustField__c.contains('Test'))
...

The error is thrown when referencing Trigger.old[i].anything

kathyanikathyani
When you do a system.debug , does Trigger.old[i].anything is have a null value?
My experience was that I did a limit on my SOQL query so later part of the code was not getting values which it is supposed get from this query.
It was displaying  a null value. I am sure it is getting null values somewhere in your case. See if you can system.debug all variables
which are getting the value from the trigger.  Print trigger values also to check values.

Null pointer exception is because it is trying to access a property on an object which has no value assigned. Object has null values and so when dereferenced
it would display the exception

Let me know if it worked.


RTHawkRTHawk
I was under the mistaken impression that Trigger.old[i] was null when in fact Trigger.old[i].somevar was null.
I put a test for null before the test for contains to solve this issue.
kathyanikathyani
So did it fix the null pointer exception or are you still getting it?
RTHawkRTHawk
The null pointer exception is now gone because I never enter the code that causes the error if the value is null. I catch the null with an if statement and do some different processing in that case.
kathyanikathyani
Awesome, there you go.
jladdersjladders
FYI: Here is the working code, I hope it helps someone!

Code:
trigger RenewalOpportunity on Opportunity (after update) {

    for (Integer i = 0; i < Trigger.new.size(); i++) {
            System.debug('checking opportunity ' + i);
            System.debug('old.isWon: ' + Trigger.old[i].isWon);
            System.debug('new.isWon: ' + Trigger.new[i].isWon);
       
    if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false && Trigger.new[i].Renewal_Opportunity__c == null && Trigger.new[i].Sale_Type__c != 'Pay Per Post') {
                        
            Double contractDays = Trigger.new[i].contract_days__c;
            Integer contractDaysInt = contractDays.intValue() - 30;
            Date endDate = Trigger.new[i].Contract_Activation_Date__c.addDays(contractDaysInt);

            System.debug('updating opportunity ' + i);
            Opportunity renewalOpp = Trigger.new[i].clone(false);
            renewalOpp.Name = 'Renewal - '+  Trigger.new[i].Name;
            renewalOpp.closedate = endDate;
            renewalOpp.Contract_Activation_Date__c = null;
            renewalOpp.stagename = '0 - Very Early Stage';
            renewalOpp.probability = 0;
            renewalOpp.ForecastCategoryName = 'Pipeline';
            renewalOpp.Contract_Length__c = null;
            renewalOpp.Objections__c = null;
            renewalOpp.NextStep = null;
            renewalOpp.Description = null;

            insert renewalOpp;           
                           
            if (Trigger.new[i].Name.startsWith('Renewal - ')) {
               renewalOpp.Name = Trigger.new[i].Name;
               update renewalOpp;
            }

            System.debug('renewal opportunity inserted' + i);                        
            System.debug('renewalOpp.id: ' + renewalOpp.ID);
            System.debug('TriggerNew[i].id: ' + Trigger.new[i].ID);
      
      if (Trigger.new[i].isWon == true && Trigger.old[i].isWon == false && Trigger.new[i].Renewal_Opportunity__c == null && Trigger.new[i].Sale_Type__c != 'Pay Per Post') {
            System.debug('Associating generated opportunity as child of closed->won opportunity');
          Opportunity newOpp = [select ID from Opportunity where id = :Trigger.new[i].ID];
          newOpp.Renewal_Opportunity__c = renewalOpp.ID;
          update newOpp;
      }
    }
  }
}