+ Start a Discussion
Steve ThurstonSteve Thurston 

Test Class 'List index out of bounds: 0' Error on Trigger.New

I'm experiencing an unexpected error in my test class for an 'after insert' trigger.  First, the trigger works just fine in Sandbox.  So the issue has something to do with how I'm setting up my test class.  When I run the test on the test class in the Developer Console, I get the error:

-------------------------
System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, leadsRoundRobin: execution of AfterInsert

caused by: System.ListException: List index out of bounds: 0

Trigger.leadsRoundRobin: line 34, column 1: []
-------------------------

If I look at the trigger leadsRoundRobin on line 34, I see that it's trying to assign the Trigger.New Lead to a variable inside the trigger:
(This is a simplified version of my trigger, including only the relevant bits)

-------------------------
trigger leadsRoundRobin on Lead (after insert) {

List<Id> triggerIds= new List<Id>();
Lead submittedLead = new Lead();

for (Lead triggerLead: trigger.new) 
        {
            triggerIds.add(triggerLead.Id);
        }

    // Get Submitted Lead Record
    submittedLeadList = [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : triggerIds];
    submittedLead = submittedLeadList[0];    <-- THIS IS LINE 34

etc....
-------------------------
Note that all this is doing, essentially, is assigning the Trigger.New Lead to 'submittedLead'.  It seems to me that the only way I could get the error 'List index out of bounds: 0' is if there IS no Trigger.New object!  That makes no sense.

Again, this is working perfectly fine running it in the Sandbox.  It's only trying to trigger it from the test class that gives this error.  The relevant bits of the Test class (I'm using 'SeeAllData=true' because my trigger references a Custom Setting):

-------------------------

@isTest(SeeAllData=true)
public class test_RoundRobin 
     { 
        // Add a Lead - Auto
            Lead testLead1 = new Lead();
                testLead1.Status = 'Open';
                testLead1.Company = 'Test Company 1';
                testLead1.LastName = 'Lead';
                testLead1.FirstName = 'Test1';
                if(contactRecordTypeMap.containsKey('Customer')) 
                    {
                        testLead1.RecordTypeId = leadRecordTypeMap.get('Customer').getRecordTypeId();
                    }
                testLead1.Phone = '1112223333';
                testLead1.Email = 'test@test.com';
                testLead1.Preferred_Contact_Method__c = 'Phone';
                testLead1.State = 'CA';
                testLead1.Requested_Quote_Types__c = 'Auto,';
                testLead1.New_Lead__c = FALSE;
            insert testLead1;   

            etc....
-------------------------

I can't figure it out.  It seems like the test class's 'insert testLead1' statement is firing the trigger, but not passing the Lead!

Any idea what I'm doing wrong?  I have a sneaky suspicion it has to do with 'SeeAllData=true', which I've never used before, but I just don't know.

Thanks!
salesforceMannsalesforceMann
Hi Steve,

The error is that you cannot assign one sObject equal to another just like that. Remeber they are objects and not primitive data types.

Change you statement to:
submittedLead = submittedLeadList[0].clone(false, false, false, false);

Furthermore, you should make you code efficient by replacing lines:
for (Lead triggerLead: trigger.new) 
        {
            triggerIds.add(triggerLead.Id);
        }

    // Get Submitted Lead Record
    submittedLeadList = [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : triggerIds];

by (note the use of trigger.new orectly) :-
submittedLeadList = [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : trigger.new];

Further reading: Take a look at the clone methog here https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject.htm

Hope this helps!!
Cheers
Mann.

Please mark as best answer if it work :)
Steve ThurstonSteve Thurston
Hi again salesforceMann,

Sorry for the delay, I tried your approach and got a different error, but had to set aside that project for a bit.

The new error appears to be the result of cloning the record.  It seems that I am actually working on the clone, so when I do an 'update' statement, it fails.  (I don't want to insert the clone, I want to update the original record.)  So I rolled back that code.

I also made my code less efficient again, changing it back into a FOR loop, so that I could add some debug statements.

After adding some additional logging, the problem appears to be related to the fact that I am inserting multiple Leads in the same test class.  i.e. in the code sample I provided, I insert 'testLead1'.  This calls my 'after insert' trigger and successfully inserts that Lead.  However, in my full test class, I then insert 'testLead2'.  It successfully enters my trigger and sees the new Lead 'testLead2', but for some reason in this case the size of my Lead list (from trigger.new) is 0, resulting in the out of bounds error.

Just to give you an idea what is going on, here is the output from my system.debug statements:

BEGIN trigger leadsRoundRobin
Entering the FOR loop to read trigger.new Lead
Lead ID:  00Q63000003KVnyEAG
Lead Name:  Test1 Lead
Exiting FOR loop
Lead List Size:  1
END trigger leadsRoundRobin
BEGIN trigger leadsRoundRobin
Entering the FOR loop to read trigger.new Lead
Lead ID:  00Q63000003KVnzEAG
Lead Name:  Test2 Lead
Exiting FOR loop
Lead List Size:  0

I'll keep adding more debug statements, but it baffles me that the first record inserts correctly, but the second record - even though it is found in trigger.new - results in a list size of 0!

 
Steve ThurstonSteve Thurston
Interesting.  Apparently I need to delete each inserted Lead before I can insert the next one!

Well, at least that means I get to move on to my next problem, "Too many SOQL Queries:  101"

But progress is progress!
salesforceMannsalesforceMann
Hi Steve, I am trying to recreate this scenario in my dev org. I need your complete trigger code to debug it.