0
votes

tl;dr - How do you make a test class wait until a specific trigger is done with its updates or inserts before continuing on with the test?

Background

I have a trigger that creates a new Portal_Content__c object whenever an Account object is created, and then associates both records with each other (see Account Trigger below).

I have also created a trigger on the Portal_Content__c object that fires when a record is deleted. When deleted, the trigger looks up the related Account record and deletes it (see Portal Content Trigger below).

My question is regarding my Portal Content Test Class (final code block below). When I run a DML insert on an Account record, the Account Trigger should populate the a.Portal_Content_Record__c field with the Portal Content record created in the Account Trigger. However, when I ran my system.debug() tests, it showed that the a.Portal_Content_Record__c field is null when the SOQL query is run. I have been able to bypass this by doing a search for the Portal Content record by matching name, but I would like to make the script more robust by searching by the exact ID.

Question

How do I make the Portal Content Test Class wait until the Account Trigger has populated the a.Portal_Content_Record__c field before moving on with the test?

--Code Blocks--

Account Trigger

trigger AccountHandler on Account (before insert, after insert, after update, after delete) {

    List<Account> alist = Trigger.New;
    List<Account> oldlist = Trigger.Old;

//  Create new Portal Content with same name as Account if Account is record type 'College/University,'
//  then assign newly created Portal Content to 'Portal Content Record' lookup field on new Account
    if(Trigger.isBefore && Trigger.isInsert){

        for(Account a : alist) {

            if (a.RecordTypeId == '012i0000001Iy1H') {
                Portal_Content__c p = new Portal_Content__c(
                    Name=a.Name,
                    RecordTypeId='012i0000001J1zZ'
                );
                insert p;

                a.Portal_Content_Record__c = p.Id;
            }
        }
    }

//  Delete Portal Content record referenced in an Account's 'Portal Content Record' lookup field
//  if the Account is deleted

    if (Trigger.isAfter && Trigger.isDelete){
        for(Account a : oldlist){
            for(Portal_Content__c p : [SELECT ID FROM Portal_Content__c WHERE ID = :a.Portal_Content_Record__c]){
                delete p;
            }
        }

    }

//  After the new Portal Content record has been created, assign the Account ID of the Account that created it
//  to the 'School SFDC ID' field on the new Portal Content record.    
    if (Trigger.isAfter && Trigger.isInsert){
        for(Account a : alist){

            List<Portal_Content__c> plist = [SELECT ID FROM Portal_Content__c WHERE Id = :a.Portal_Content_Record__c];

            for(Portal_Content__c p : plist){
                p.School_SFDC_ID__c = a.Id;
                update p;
            }

        }
    }

//  Prevent more than one Account from being assigned to a single Portal Content record
    if (Trigger.isAfter && Trigger.isUpdate) {
        for(Account a : alist){
            if (a.Portal_Content_Record__c != null){
                List<Account> alist = [SELECT ID FROM Account WHERE Portal_Content_Record__c = :a.Portal_Content_Record__c];
                system.debug('alist: ' + alist);
                if (alist.size() > 1) {
                    a.addError('The Portal Content record you selected is already associated with another School. Please select a different Portal Content record');
                }
            }
        }
    }
}

Portal Content Trigger

trigger PortalContentHandler on Portal_Content__c (before insert, after update, after insert, after delete) {

//  If Portal Content is deleted and Account is tied to Account record, delete Account record
    if(Trigger.isAfter && Trigger.isDelete){
        List<Portal_Content__c> plist = Trigger.old;
        for(Portal_Content__c p : plist) {
            List<Account> alist = [SELECT ID FROM Account WHERE Id = :p.School_SFDC_ID__c];
            for(Account a : alist){
                delete a;
            }       
        }
    }

//  If more than one Portal Content with the same name, prevent new Portal Content record from being created
    else if(Trigger.isAfter && (Trigger.isUpdate || Trigger.isInsert)){
        List<Portal_Content__c> plist = Trigger.New;
        for(Portal_Content__c p : plist){
            List<Portal_Content__c> pquery = [SELECT ID FROM Portal_Content__c WHERE Name = :p.Name];
            if(pquery.size() > 1){
                p.addError('There is already a Portal Content record with this name. Please select a different name.');
            }
        }
    }
}

Portal Content Test Class

@isTest
public class PortalContentHandlerTest {

    @isTest static void createThenDeletePortalContent(){
        Account a = new Account(Name='deletePortalTest',RecordTypeId='012i0000001Iy1H');
        insert a;

        List<Portal_Content__c> plist = [SELECT ID FROM Portal_Content__c WHERE Name = :a.Name];//Id = :a.Portal_Content_Record__c];

        system.debug('Delete Info: a.Id = ' + a.Id + ', Portal_Content_Record = ' + a.Portal_Content_Record__c+ ', plist = ' + plist);
        for(Portal_Content__c p : plist){
            delete p;            
        }
        system.debug('Delete Info: a.Id = ' + a.Id);
        List<Account> checklist = [SELECT ID FROM Account WHERE Id = :a.Id];
        system.debug(checklist);
        system.assertEquals(0, checklist.size());
    }
1

1 Answers

0
votes

I have tested it in my Org. Please find my comments below.

  • According to your requirement, I have a trigger that creates a new Portal_Content__c object whenever an Account object is created, and then associates both records with each other (see Account Trigger below).
    I see there is a relationship on the Account(Portal_Content_Record__c ) and the Portal Content (School_SFDC_ID__c). You are setting the Portal_Content_Record__c. but you need to link the School_SFDC_ID__c as well to fulfill your requirement. Please find the below code

    trigger AccountHandler on Account (before insert, after insert, after update, after delete) {
    
            List<Account> alist = Trigger.New;
            List<Account> oldlist = Trigger.Old;
    
        //  Create the new Portal Content with the same name as Account if Account is record type College/University,
        //  then assign newly created Portal Content to Portal Content Record lookup field on new Account
            if(Trigger.isBefore && Trigger.isInsert){
    
                for(Account a : alist) {
    
                    if (a.RecordTypeId == '012i0000001Iy1H') {
                        Portal_Content__c p = new Portal_Content__c(
                            Name=a.Name,
                            RecordTypeId='012i0000001J1zZ',
                            School_SFDC_ID__c = a.id
                        );
                        insert p;
    
                        a.Portal_Content_Record__c = p.Id;
                    }
                }
            }
        }
    
  • I see the only thing is delete is not getting covered in PortalContentHandler because it doesn't meet with the condition for List<Account> alist = [SELECT ID FROM Account WHERE Id = :p.School_SFDC_ID__c]; Populate it when you are creating Portal Content as describe in the above point.

  • Also, you need to change your test class as there is no data for Portal Content that you are trying to query. In the test class, you get the data what you created there only. The one which gets created by AccountHandler won't be part of your test class. Create the same data as you are creating in the trigger.

    @isTest 
    public class PortalContentHandlerTest {
    
    @isTest static void createThenDeletePortalContent(){
        Account a = new 
        Account(Name='deletePortalTest',RecordTypeId__c='012i0000001Iy1H');
        insert a;
        Portal_Content__c p = new Portal_Content__c(
            Name=a.Name,
            RecordTypeId__c='012i0000001J1zZ',
            School_SFDC_ID__c = a.id
        );
        insert p;
        delete p; 
    }
    
    }