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
assuming that you want all inserted opportunities to be processed.