[SalesForce] Getting a System.DMLException:Insert failed error

I"ve created a trigger which is relatively short

trigger trig_Opportunity_CreateOppOwner on Opportunity (before update,before insert) {

    List<id>OppsID = new List<id>(); //List that will hold all id of all new Opportunities owners

    for(Opportunity Opp:Trigger.new){ //Loop that only retrives new versions of the Opportunity 
        if (trigger.oldMap.get(Opp.id).Op_Owner__c != trigger.oldMap.get(Opp.id).OwnerId)//Checks to see if they are new owners and not already on the owner list.
            OppsId.add(Opp.ID);//adds all new opportunity owners to OppsId list. 
    }
    List<Opportunity> oppsFromDb =  [SELECT id, OwnerId FROM Opportunity WHERE id IN:OppsID];   
    for(Opportunity useOpps:oppsFromDb){                            
        trigger.newMap.get(useOpps.Id).Op_Owner__c = useOpps.OwnerId;
    }

I've also created the following test class for it:

    @isTest

public with sharing class Test_Trig_Opportunity_CreateOppOwner {
    static testMethod void testTriggerOpp(){

        //initialize test variables (called from TestUtil class)         
    Contact testContact1 = TestUtil.initContact();
    Account testAccount1 = TestUtil.initAccount();      
    User testUser1 = TestUtil.initUser(); 
    Opportunity testOpp1 = TestUtil.initOpportunity(testAccount1,testContact1); 

    testOpp1.OwnerId = testUser1.Id;

    Test.startTest();
    //1. First check to see if it's a brand new Owner ID
   System.debug('first test'); // Creating a new opportunity to start Trigger
    Opportunity newtestOpp1 = TestUtil.initOpportunity(TestUtil.initAccount(),TestUtil.initContact());
      User testUser2 = TestUtil.initUser(); 
      newtestOpp1.OwnerId = testUser2.Id;
    System.debug('The opp owner should be null' + newtestOpp1.Op_Owner__c);
    try{        
        insert newtestOpp1;
        }catch(DMLException d){System.debug(d);}
    System.debug('The opp owner should not be null' + newtestOpp1.Op_Owner__c); 
    //2. Check to see if OwnerId exists but doesn't match in Op_Owner__c
    Opportunity newtestOpp = [SELECT id, OwnerId, Op_Owner__c FROM Opportunity WHERE name = 'JFTestOpportunity'];
    //3. Does not exist in either       
    Test.stopTest();// Test ended


    }
}

The TestUtil class that is called above is shown below:

    @isTest
public class TestUtil 
{
    public static Contact initContact(){
    /**
        *   Create a Contact
        *   Insert Contact into DB
        *   Return Contact back into testPage in order to use information
    **/             
        Contact testContact = new Contact (
                    firstName = 'Firstly', lastName = 'Lastly', email = 'test@test.com'
                    );
        insert testContact;
        return testContact;
    }



    public static Account initAccount(){
    /**
        *   Create an Account
        *   Insert Account into DB
        *   Return Account back into testPage in order to use information
    **/     
        Account testAccount = new Account (
                    name = 'JFTestAccount' , type = 'Potential Customer' , ShippingState= 'Alabama', ShippingCountry= 'United States', BillingState= 'Alabama',BillingCountry= 'United States'      
                    );
        insert testAccount;
        return testAccount;
    }

      public static User initUser(){
   /**
        * Create a User
        * Insert User into DB
        * Return User back into testPage in order to use information    
   **/
        User testUser = new User (//for future reference, make sure to write UserRoleID and ProfileId when creating new Users
                    lastName = 'Lastly', alias = 'newalias', email = 'test@testOwnerId.com', username = 'user1@testUser.com',  
                    CommunityNickname = 'JFtestrole', UserRoleID = '00E40000000xIjN', ProfileId = '00e30000000fjIk', EmailEncodingKey = 'ISO-8859-1',
                    TimeZoneSidKey = 'America/New_York', LocaleSidKey = 'en_CA', LanguageLocaleKey = 'en_US', DigestFrequency = ''
                    );


        insert testUser;
        return testUser;
   }

   public static Opportunity initOpportunity(Account testAccount, Contact testContact){   
    /**
        *   Create an Opportunity , getting the Hyperstream RecordType ID
        * Insert Opportunity into DB 
        *   Return Opportunity back into testpage to use information  
    **/                             
        RecordType[] recHyperStream = [SELECT 
                                                                        description, id, sObjectType, businessProcessId 
                                                                    FROM 
                                                                        RecordType 
                                                                    WHERE 
                                                                        sObjectType='Opportunity' AND description = 'HyperStream Services' 
                                                                    ];                                                  
        Opportunity testOpp = new Opportunity (
                    name = 'JFTestOpportunity' , accountId = testAccount.id , opportunity_Contact__c = testContact.id,
                    closeDate = date.today() , stageName = 'Draft (1%)' , nextStep ='tstSomething',
                    end_User__c = testAccount.id, end_User_Contact__c = testContact.id,
                    client_PO__c = 'PO123456', recordTypeId = recHyperStream[0].Id
                    );
        insert testOpp;
        return testOpp;                                                     
    }

The System.DMLException seems to have occurred in Class.TestUtil.initOpportunity on the insert testOpp line as shown above.

Here is the full error message:

System.DmlException:Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, trig_Opportunity_CreateOppOwner: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.trig_Opportunity_CreateOppOwner

I've changed the before insert to after insert which gave the same error, tried to activate the trigger only on before updates only and I still receive the same error. I've added in the try catch in my test class Test_Trig_Opportunity_CreateOppOwner but that doesn't seem to have done the trick. Does anyone know what the problem is?

Best Answer

trigger.oldMap is only available in Update / Delete triggers. Your trigger is before update, before insert.

Since it is null when you're inserting a record, it is causing a NullPointerException.

You could change the condition to

if (trigger.isInsert || (trigger.isUpdate && trigger.oldMap.get(Opp.id).Op_Owner__c != trigger.oldMap.get(Opp.id).OwnerId))

assuming that you want all inserted opportunities to be processed.

Related Topic