function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mike RMike R 

Apex Trigger Test Error - 0 Stack Trace

I am using a Marketing Automation Tool that will Create a Contact (not using Leads), I created a trigger to create Account (FirstName LastName and - Account, I get error and trigger and test class below:

Error Message System.ListException: List index out of bounds: 0
Stack Trace Class.CreateAccountFromContact_UnitTest.runTest: line 14, column 1

trigger CreateAccountFromContact on Contact (before insert) {
//Collect list of contacts being inserted without an account
    List<Contact> needAccounts = new List<Contact>();
    for (Contact c : trigger.new) {
        if (String.isBlank(c.accountid)) {
            needAccounts.add(c);
        }
    }
   
    if (needAccounts.size() > 0) {
        List<Account> newAccounts = new List<Account>();
        Map<String,Contact> contactsByNameKeys = new Map<String,Contact>();
        //Create account for each contact
        for (Contact c : needAccounts) {
            String accountName = c.firstname + ' ' + c.lastname + ' ' + ' - Account ';
            contactsByNameKeys.put(accountName,c);
            Account a = new Account(name=accountName);
            newAccounts.add(a);
        }
        insert newAccounts;
       
              
  }     
}
 
@isTest
public with sharing class CreateAccountFromContact_UnitTest {
    @isTest
    public static void runTest(){
        String firstname = 'first';
        String lastname = 'last';
               
        //Create contact
        Contact c = new Contact(firstname=firstname, lastname=lastname);
        insert c;
        
        //Verify account
        c = [select id, accountid, firstname, lastname from Contact where id =:c.Id][0];
        Account a = [select id, name from Account where id = :c.accountId][0];
        
        system.assertEquals(firstname + ' ' + lastname + ' ' + ' - Account ', a.name);
        
        
    }
}
Best Answer chosen by Mike R
ShotShot
You forgot to add this logic in trigger:
trigger CreateAccountFromContact on Contact (before insert) {
//Collect list of contacts being inserted without an account
    List<Contact> needAccounts = new List<Contact>();
    for (Contact c : trigger.new) {
        if (String.isBlank(c.accountid)) {
            needAccounts.add(c);
        }
    }
   
    if (needAccounts.size() > 0) {
        List<Account> newAccounts = new List<Account>();
        Map<String,Contact> contactsByNameKeys = new Map<String,Contact>();

        //Create account for each contact
        for (Contact c : needAccounts) {
            String accountName = c.firstname + ' ' + c.lastname + ' ' + ' - Account ';
            contactsByNameKeys.put(accountName,c);
            Account a = new Account(name=accountName);
            newAccounts.add(a);
        }
        insert newAccounts;

        for(Account acc :newAccounts){
            contactsByNameKeys.get(acc.Name).AccountId = acc.Id;
        }      
  }     
}

 

All Answers

KevinPKevinP
Couple of notes here.
  1. Thank you for posting code. In the future, please use the <> button on the toolbar above to paste code. This gives us line #'s and formatting to make this much easier to read, and to provide feedback. 
Here's teh formatted version of your code:
trigger CreateAccountFromContact on Contact (before insert) {
//Collect list of contacts being inserted without an account
    List<Contact> needAccounts = new List<Contact>();
    for (Contact c : trigger.new) {
        if (String.isBlank(c.accountid)) {
            needAccounts.add(c);
        }
    }
   
    if (needAccounts.size() > 0) {
        List<Account> newAccounts = new List<Account>();
        Map<String,Contact> contactsByNameKeys = new Map<String,Contact>();
        //Create account for each contact
        for (Contact c : needAccounts) {
            String accountName = c.firstname + ' ' + c.lastname + ' ' + ' - Account ';
            contactsByNameKeys.put(accountName,c);
            Account a = new Account(name=accountName);
            newAccounts.add(a);
        }
        insert newAccounts;
       
              
  }     
}

And your Test:
@isTest
public with sharing class CreateAccountFromContact_UnitTest {
    @isTest
    public static void runTest(){
        String firstname = 'first';
        String lastname = 'last';
               
        //Create contact
        Contact c = new Contact(firstname=firstname, lastname=lastname);
        insert c;
        
        //Verify account
        c = [select id, accountid, firstname, lastname from Contact where id =:c.Id][0];
        Account a = [select id, name from Account where id = :c.accountId][0];
        
        system.assertEquals(firstname + ' ' + lastname + ' ' + ' - Account ', a.name);
        
        
    }
}

 
KevinPKevinP
With the line numbers in place, I can see that line 14 is:
Account a = [select id, name from Account where id = :c.accountId][0];

This, combined with your error message indicates that index 0 of the list of results isn't logically available.

Because you're assigning the soql query to a single account rather than a list of account you don't have any indexes to reference. Instead of using  line 14 from above; try this one.
Account a = [select id, name from Account where id = :c.accountId];

 
Mike RMike R
I am still geting the same error, thanks for your time and assitance
KevinPKevinP
Mike,

Are you sure your contact is being inserted then? is it throwing any validation errors? what do the logs say?
Mike RMike R
I looked at the log and a contact Id is created but when it gets to the account

09:47:29:405 SOQL_EXECUTE_BEGIN [14]|Aggregations:0|SELECT id, name FROM Account WHERE id = :tmpVar1

I get the fatal error
ShotShot
You forgot to add this logic in trigger:
trigger CreateAccountFromContact on Contact (before insert) {
//Collect list of contacts being inserted without an account
    List<Contact> needAccounts = new List<Contact>();
    for (Contact c : trigger.new) {
        if (String.isBlank(c.accountid)) {
            needAccounts.add(c);
        }
    }
   
    if (needAccounts.size() > 0) {
        List<Account> newAccounts = new List<Account>();
        Map<String,Contact> contactsByNameKeys = new Map<String,Contact>();

        //Create account for each contact
        for (Contact c : needAccounts) {
            String accountName = c.firstname + ' ' + c.lastname + ' ' + ' - Account ';
            contactsByNameKeys.put(accountName,c);
            Account a = new Account(name=accountName);
            newAccounts.add(a);
        }
        insert newAccounts;

        for(Account acc :newAccounts){
            contactsByNameKeys.get(acc.Name).AccountId = acc.Id;
        }      
  }     
}

 
This was selected as the best answer
Mike RMike R
I edited it and get this error?

Error MessageSystem.AssertException: Assertion Failed: Expected: first last - Account , Actual: first last - AccountStack TraceClass.CreateAccountFromContact_UnitTest.runTest: line 16, column 1
ShotShot
Looks like in trigger SF removes space if its the last element in string. Try to change this line to:
system.assertEquals(firstname + ' ' + lastname + ' ' + ' - Account', a.name);

 
Mike RMike R
That did it thanks

Mike