2

I'm having some difficulties with a test class I'm writing for an Apex Trigger. When I test the trigger manually, I have no problems. Everything works perfectly!

However, in my test class, I'm having some difficulties. The trigger works after update on the Account object (it is designed to update a value on all child Contact records when a certain field in the Account object is updated, so the Account is not being updated in the trigger), so when I trigger an update in the test class, the error is thrown. If I throw the update into a try/catch block, then the items in the catch are always triggered.

Error (updated):

08:45:08:262 CODE_UNIT_FINISHED AccountClientTypeUpdater on Account trigger event AfterUpdate for [001Z0000002UFfa]
08:45:08:264 DML_END [20]|
08:45:08:264 EXCEPTION_THROWN [20]|System.DmlException: Update failed. First exception on row 0 with id 001Z0000002UFfaIAG; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountClientTypeUpdater: execution of AfterUpdate
08:45:06:000 EXCEPTION_THROWN caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Contact.AccountId
08:45:06:000 EXCEPTION_THROWN Trigger.AccountClientTypeUpdater: line 18, column 1: []
08:45:08:265 FATAL_ERROR System.DmlException: Update failed. First exception on row 0 with id 001Z0000002UFfaIAG; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountClientTypeUpdater: execution of AfterUpdate
08:45:06:000 FATAL_ERROR caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Contact.AccountId
08:45:06:000 FATAL_ERROR Trigger.AccountClientTypeUpdater: line 18, column 1: []
08:45:06:000 FATAL_ERROR Class.TriggerUnitTests.accountClientTypeTriggerTest1: line 20, column 1
08:45:08:265 FATAL_ERROR System.DmlException: Update failed. First exception on row 0 with id 001Z0000002UFfaIAG; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountClientTypeUpdater: execution of AfterUpdate
08:45:06:000 FATAL_ERROR caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Contact.AccountId
08:45:06:000 FATAL_ERROR Trigger.AccountClientTypeUpdater: line 18, column 1: []
08:45:06:000 FATAL_ERROR Class.TriggerUnitTests.accountClientTypeTriggerTest1: line 20, column 1

Trigger:

trigger AccountClientTypeUpdater on Account (after update) {
    List<Contact> contacts_to_update = new List<Contact>();

    //Get a list of all the account ID's that were updated
    List<Id> account_ids = new List<Id>();
    account_ids.addAll(System.Trigger.newMap.keySet());

    //Get a list of all child contacts 
    List<Contact> all_contacts = [
        SELECT Id, Account_Client_Type__c, Account_Client_Type_Text_Only__c 
        FROM Contact 
        WHERE AccountId IN :account_ids
    ];

    for (Account account : System.Trigger.new) {
        if (!all_contacts.isEmpty()) {
            for (Contact contact : all_contacts) {
                if (account.Id == contact.AccountId) { //Only update the contacts of the current account
                    if (String.valueOf(account.Client_Type__c) != String.valueOf(contact.Account_Client_Type_Text_Only__c)) {
                        contact.Account_Client_Type_Text_Only__c = String.valueOf(account.Client_Type__c);
                        contacts_to_update.add(contact);
                    }
                }
            }
        } else {
            continue;
        }
    }

    if (!contacts_to_update.isEmpty()) {
        update contacts_to_update;
    }
}

Test Class (updated):

@isTest
public class TriggerUnitTests {
    static testMethod void accountClientTypeTriggerTest1() {
        Account parent_account = new Account(Name = 'Test Company');
        parent_account.Client_Type__c = 'LinkUp Prospect';
        insert parent_account;

        Contact child_contact = new Contact();
        child_contact.accountId = parent_account.Id;
        child_contact.FirstName = 'Jane';
        child_contact.LastName = 'Doe';
        child_contact.Email = 'Jane.Doe@example.com';
        insert child_contact;

        Account account = [SELECT Id, Client_Type__c FROM Account WHERE Id = :parent_account.Id];
        account.Client_Type__c = 'LinkUp Customer';
        update account;
        //try {
        //    update parent_account;
        //} catch (System.DMLException e) {
        //    System.debug('Account record could not be updated.');
        //}
    }
}

Update: The issue in question ended up being because of line 10 of the trigger. The code went through a lot of changes while I was trying to write it, and at some point the SELECT statement lost the AccountId field, causing line 18 to flip out. Thanks for all the help!

  • 1
    Is there anything more descriptive in the debug logs? When you run the tests you should see a new log entry in the developer console. – Matt Lacey May 21 '13 at 4:15
  • Hi @LaceySnr, the logs are quite long, but I've added all the information that surrounded the error in question. It looks like the issue is because of Line 10 of the trigger. Because of all the edits it went through, AccountId was excluded from the SELECT statement I used to gather all the contacts from the database. Silly me! Thanks for the help! – Lisa May 21 '13 at 14:08
1

For the update operation in test class,

Account acc=[select id,client_type__c from Account where id=:parent_account.id limit 1];

acc.client_type__c = 'LinkUp Prospect';

update acc;

This should fix the issue

Inserting and updating same variable is causing this exception. After the insert operation we can query back the record and then update the record.

  • Since it is only a test, and the information isn't being committed, will the query still work? – Lisa May 21 '13 at 13:22
  • Data will be committed in test context and hence no doubt it will return data and will work – Mohith Shrivastava May 21 '13 at 13:43
  • Ok, I've figured out my issue. The trigger ended up going through about a zillion edits, and at some point, the AccountId field was removed from the query that pulls all the contacts in. Thanks for all your help! – Lisa May 21 '13 at 14:07
  • Glad you got it sorted - for the record everything does get committed and the like, it just gets rolled back at the end of the test context. This allows you to create new users etc. for testing knowing they'll not be there afterwards. – Matt Lacey May 21 '13 at 23:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.