+ Start a Discussion
noobfnnoobfn 

Issue with Test class coverage

Hi,

I have no idea where my error is, debug log message is "System.NullPointerException: Attempt to de-reference a null object"  and error titled "Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, updateContactsOnAddressChange: execution of BeforeInsert" 

 

I guess I'm confused because because of my trigger before insert and after update.

 

Any help appreciate it!

 

This is my trigger: 

trigger updateContactsOnAddressChange on Account (before Insert, after update) {
     
        // I want to find the new address/values on Account by map Id Keys 
         
        Map<Id, Account> acctsWithNewAddresses = new Map<Id, Account>();
     
        // Trigger.new holds my list of the Accounts that will be updated        
        // This loop iterates over the list, and adds any that have new
        // addresses to the acctsWithNewAddresses map. 
         
        for (Integer i = 0; i < Trigger.new.size(); i++) {
            if (   (Trigger.old[i].BillingCity != Trigger.new[i].BillingCity)
                || (Trigger.old[i].BillingCountry != Trigger.new[i].BillingCountry)
                || (Trigger.old[i].BillingPostalCode != Trigger.new[i].BillingPostalCode)
                || (Trigger.old[i].BillingState != Trigger.new[i].BillingState)
                || (Trigger.old[i].BillingStreet != Trigger.new[i].BillingStreet))  {
                acctsWithNewAddresses.put(Trigger.old[i].id,Trigger.new[i]);
            }
        }
                         
        List<Contact> contacts = [SELECT id, accountid, MailingCity, MailingCountry, MailingPostalCode,MailingState, MailingStreet
                          FROM Contact
                          WHERE accountId in :acctsWithNewAddresses.keySet()];
            
                    List<Contact> updatedContacts = new List<Contact>();
     System.debug('Kellers ' + contacts);


        //iterating over each contact in Account
        for (Contact c : contacts) {
            Account parentAccount = acctsWithNewAddresses.get(c.accountId);
            c.MailingStreet = parentAccount.BillingStreet;
            c.MailingCity = parentAccount.BillingCity ;
            c.MailingCountry = parentAccount.BillingCountry ;
            c.MailingPostalCode = parentAccount.BillingPostalCode ;
            c.MailingState = parentAccount.BillingState ;
            c.MailingStreet = parentAccount.BillingStreet ;
    
     
         // Rather than insert the contacts individually, add the         
            // contacts to a list and bulk insert it. This makes the         
            // trigger run faster and allows us to avoid hitting the         
            // governor limit on DML statements 

            updatedContacts.add(c);
        }
        update updatedContacts;
    }

 This is my test: 

@isTest
public class TestUpdateContactsOnAddressChange{
    static testmethod void testAddressChange() {
       //create an account and create account address
        Account sAcct = new Account();
       	sAcct.Name = 'Test Account';
        sAcct.BillingStreet = '11 Initial Street'; 
        sAcct.BillingCity = 'Rochester';
        sAcct.BillingPostalCode = '12456';
        sAcct.BillingState = 'NY';
        sAcct.BillingCountry = 'USA';
       	 insert sAcct;
       	
                
        //create contact for Account "Test Account" and create contact address
        Contact[] sContact = new Contact[]{
        	new contact(
        MailingStreet = '1 Initial street',
       	MailingCity = 'Rochester',
        MailingPostalCode = '12456',
        MailingState = 'NY',
        MailingCountry = 'USA',
        accountid = sAcct.id),
                
        	new contact(
        MailingStreet = '2 Initial street',
        MailingCity = 'Rochester',
        MailingPostalCode = '12456',
        MailingState = 'NY',
        MailingCountry = 'USA',
        accountid = sAcct.id),
       
        	new contact(
        MailingStreet = '3 Initial street',
        MailingCity = 'Rochester',
        MailingPostalCode = '12456',
        MailingState = 'NY',
        MailingCountry = 'USA',
                accountid = sAcct.id) };
       
        insert sContact;
        
        //change address on account
        sAcct.BillingStreet = '11 Updated Street'; 
        sAcct.BillingCity = 'Updated City';
        sAcct.BillingPostalCode = '99999';
        sAcct.BillingState = 'PA';
        sAcct.BillingCountry = 'Mexico';
          
        Test.startTest();
         update sAcct;//this should fire my trigger.
        Test.stopTest();
             
               
        sContact = [Select id, accountid, MailingStreet, MailingCity,MailingPostalCode, MailingState, MailingCountry from 
                     contact where id in: sContact];
        
        //check if account updated address match each contact address
       	System.assertEquals(sAcct.BillingStreet, sContact[0].Mailingstreet); 
        System.assertEquals(sAcct.BillingCity, sContact[0].MailingCity); 
        System.assertEquals(sAcct.BillingPostalCode, sContact[0].MailingPostalCode); 
        System.assertEquals(sAcct.BillingState, sContact[0].MailingState);
        System.assertEquals(sAcct.BillingCountry, sContact[0].MailingCountry);
        
        //check addresses didn't match before update
        System.assert(sContact[1].MailingStreet != sAcct.BillingStreet); 
        System.assert(sContact[1].MailingCity != sAcct.BillingCity); 
        System.assert(sContact[1].MailingPostalCode != sAcct.BillingPostalCode); 
        System.assert(sContact[1].MailingState != sAcct.BillingState);
        System.assert(sContact[1].MailingCountry != sAcct.BillingCountry);
        
    }
}

 noobfn

Best Answer chosen by Admin (Salesforce Developers) 
Saikishore Reddy AengareddySaikishore Reddy Aengareddy

You will need to update your code for each event...

 

Look here for more information on Trigger context variables and their usage..

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm

 

There will be nothing called Trigger.old in before insert. 

 

(Trigger.old[i].BillingCity != Trigger.new[i].BillingCity)

All Answers

Saikishore Reddy AengareddySaikishore Reddy Aengareddy

You will need to update your code for each event...

 

Look here for more information on Trigger context variables and their usage..

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm

 

There will be nothing called Trigger.old in before insert. 

 

(Trigger.old[i].BillingCity != Trigger.new[i].BillingCity)
This was selected as the best answer
noobfnnoobfn

I see it.  I wanted to do this trigger using map and using trigger.old and new worked.  Initially I used a list as follows: 

trigger TestingAccountUpdate on Account (Before Insert, After Update) 
{
    // List to holds all the ids from all the accounts 
    List<id> ids = new List<id>(); 
    
      // Trigger.new holds all the ids from all the accounts  
             for(Account acc: Trigger.new)    {
               ids.add(acc.id);    }        
       
    //this will fetch all the contacts which are associated with IN ids. This query should never be inside a for loop.
       List<Contact> listcon = [Select id, accountid, MailingStreet, MailingCity, MailingState, MailingPostalCode, 
       MailingCountry FROM Contact WHERE accountid IN: ids];        
       
       //System.debug('rogers ' + Account.BillingStreet);  result is rogers BillingStreet
              
                   
       if(trigger.isUpdate)    
       {               
       //for(Account acc:Trigger.new){ } 
       
       //this list holds my contacts
       List<Contact> updatelist = new List<Contact>();
         for(Account acc:Trigger.new){
         for(Contact c:listcon){
           if(c.AccountId == acc.Id){
            c.mailingstreet = acc.billingstreet;
            c.mailingCity = acc.billingCity ;
            c.mailingCountry = acc.billingCountry ;
            c.mailingPostalCode = acc.billingPostalCode ;
            c.mailingState = acc.billingState ;
            c.mailingStreet = acc.billingStreet ;
   
     updatelist.add(c);
           System.debug('Lemon  ' + acc.BillingStreet);
               }
             }
           }
       
       // This loop iterates over the list, and adds any that have new address
       /*for(integer i =0; i < listcon.size(); i++)       
         {  //Account parentAccount = Account.get;
            listcon[i].MailingStreet='dont know';  }  */ 
      
       update listcon;    
        }

 So, is there any other way I can still use map in my trigger and test my work in my trigger using map? 

noobfnnoobfn

thank you. After thinking about this, it made sense then to remove "before insert", the test cover the trigger now.  

 

noobfn