0

I am getting the following error in my test class. The insert tests work fine but the update test is failing.

Error:

20:02:22:421 FATAL_ERROR System.ListException: List index out of bounds: -1
20:02:22:426 FATAL_ERROR System.DmlException: Update failed. First exception on row 0 with id a003X000012swL2QAI; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, ContactTrigger: execution of BeforeUpdate

I don't understand where the out of bounds error is arising.

Test Class:

@isTest
public class TestContactTrigger {

@isTest static void TestInsertContactSinglePositive() {
    // Test data setup
    // Create one account with one contact by calling a utility method
    Account[] accts = TestDataFactory.createAccountsWithContacts(1,1);

    Contact cont = [SELECT Id FROM Contact LIMIT 1];
    // Perform test
    Test.startTest();
    Commission__c comm = new Commission__c(Amount__c=2000, Awarded_To__c=cont.Id, Awarded_To__r=cont); //interesting had to explicitly declare __c and __r
    insert comm;
    Test.stopTest();

    cont = [SELECT Primary__c FROM Contact];             
    System.assert(cont.Primary__c == true);
}

@isTest static void TestInsertContactMultiplePositive() {
    // Test data setup
    // Create 10 accounts with 3 contacts by calling a utility method
    Account[] accts = TestDataFactory.createAccountsWithContacts(10,3);

    Contact cont = [SELECT Id FROM Contact LIMIT 1];
    // Perform test
    Test.startTest();
    Commission__c comm = new Commission__c(Amount__c=2000, Awarded_To__c=cont.Id, Awarded_To__r=cont); //interesting had to explicitly declare __c and __r
    insert comm;
    Test.stopTest();

    cont = [SELECT Primary__c FROM Contact WHERE Id = :cont.id];             
    System.assert(cont.Primary__c == true);
}

@isTest static void TestUpdateContactPositive() {
    // Test data setup

    Account accountOne = new Account(Name='Account One');
    insert accountOne;
    Contact contactOne = new Contact(LastName='Doe', AccountId=accountOne.Id, Primary__c = false);
    insert contactOne;

    Account accountTwo = new Account(Name='Account Two');
    insert accountTwo;
    Contact contactTwo = new Contact(LastName='Deer', AccountId=accountTwo.Id, Primary__c = false);
    insert contactTwo;

    Commission__c commSmall = new Commission__c(Amount__c=20, Awarded_To__c=contactOne.Id, Awarded_To__r=contactOne);
    insert commSmall;
    Commission__c commLarge = new Commission__c(Amount__c=2000, Awarded_To__c=contactTwo.Id, Awarded_To__r=contactTwo);
    insert commLarge;

    commLarge.Amount__c = 10;
    // Perform test
    Test.startTest();
    update CommLarge;
    Test.stopTest();

    Contact result = [SELECT Primary__c FROM Contact WHERE Id = :contactOne.id];             
    System.assert(result.Primary__c == true);
} 
}

Trigger Handler Class:

public class ContactTriggerHandler {

public static void checkPrimary(List<Contact> triggerContacts){
    List<Account> accountList = getAccounts(triggerContacts);
    List<Contact> otherContacts = getContacts(triggerContacts, accountList);
    Map<Id, List<Contact>> combinedContacts = combineContacts(otherContacts, triggerContacts, accountList);

    for(Id idValue : combinedContacts.keySet()){
        Double currentMax =0.00;
        Integer indexOfPrimary;
        for(Contact aContact : combinedContacts.get(idValue)){
            aContact.Primary__c = false;
            if(aContact.Total_Commission_Earned__c > currentMax){
                currentMax = aContact.Total_Commission_Earned__c;
                indexOfPrimary = combinedContacts.get(idValue).indexOf(aContact);
            }
        }
        if(currentMax == combinedContacts.get(idValue).get(indexOfPrimary).Total_Commission_Earned__c && indexOfPrimary >= 0){
            combinedContacts.get(idValue).get(indexOfPrimary).Primary__c = true;
        }
    }

}




private static List<Account> getAccounts(List<Contact> contactList){
    Set<Id> accountIDs = new Set<Id>();

    for(Contact aContact : contactList){
        accountIDs.add(aContact.AccountId);
    }
    List<Account> accountList = new List<Account>([SELECT Id FROM ACCOUNT WHERE Id IN :accountIDs]);
    return accountList;
}

private static List<Contact> getContacts(List<Contact> triggerContacts, List<Account> accountList){
    Set<Id> accountIDs = new Set<Id>();

    for(Account anAccount : accountList){
        accountIDs.add(anAccount.Id);
    }        
    List<Contact> contactList = new List<Contact>([SELECT Id, AccountId, Total_Commission_Earned__c, Primary__c FROM Contact WHERE AccountId IN :accountIDs]);

    for(Contact aContact : contactList){
        if(triggerContacts.contains(aContact)){
            contactList.remove(contactList.indexOf(aContact));
        }
    }

    return contactList;
}

private static Map<Id, List<Contact>> combineContacts(List<Contact> accountContacts, List<Contact> triggerContacts, List<Account> accountList){
    List<Contact> allContacts = new List<Contact>();
    allContacts.addAll(accountContacts);
    allContacts.addAll(triggerContacts);

    Map<Id, List<Contact>> combinedContacts = new Map<Id,List<Contact>>();

    for(Account a : accountList){
        List<Contact> contactList = new List<Contact>();
        for(Contact c : allContacts){
            if(c.AccountId == a.Id){
                contactList.add(c);
            }
        }
        combinedContacts.put(a.Id, contactList);
    }

    return combinedContacts;
}
}

Trigger Code:

trigger ContactTrigger on Contact (before insert, before update) {
if(Trigger.isBefore){
    if(Trigger.isInsert){
        // other logic here
    }else if(Trigger.isUpdate){
        ContactTriggerHandler.checkPrimary(Trigger.new);
    }else if(Trigger.isDelete){
        // other logic here
    }
}
}
2
  • Please include the stack trace and identify the specific line(s) where these errors occur.
    – David Reed
    Oct 24, 2019 at 19:19
  • Due to the error message, I am guessing it has something to do with the reference of indexOfPrimary and it trying to access an empty or null array Oct 24, 2019 at 19:21

1 Answer 1

0

List.indexOf can return -1 if no match is found. If so, you must not attempt to use that index. The following change may help:

if(indexOfPrimary > -1 && currentMax == combinedContacts.get(idValue)[indexOfPrimary].Total_Commission_Earned__c && indexOfPrimary >= 0){

Please note that you should use [index] instead of .get(index) for performance reasons. Your code has other issues as well, such as using a loop inside of a loop. These code inefficiencies may cause errors when updating 200 records at once. Please make sure your unit test is testing a list of 200 records.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .