+ Start a Discussion
Stephanie_ArceStephanie_Arce 

System.AssertEquals, Updating the Same Record with a Trigger

Hi, I'm trying to build a trigger that acts to update a picklist with the value of another picklist (located on the same record).

 

The custom object this trigger is on needs to be restricted but we also need to let all users create and edit records here to a degree, so we have a system where they can "request an update" to the record using identical fields to the actual fields/the fields used in a report. They can fill in one picklist, but the "actual" picklist field should remain as-is until a user with additional permissions changes a checkbox from false to true. I've built everything else we need for this using workflows, but I've learned with picklists you can only go up/down the list or set it to a specific value.

 

I tried changing the picklist to a checkbox as we only have 2 possible values, but ran into the same issue where I can only set it to true or false, not the value of another checkbox. We may also add a third option so I'd like to keep this field as a picklist.

 

I have a trigger and test class written but I get an error when running my test:

System.DmlException: Update failed. First exception on row 0 with id a0DQ0000003vFohMAE; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CRHUpdateWorkStatus: execution of BeforeUpdate


caused by: System.DmlException: Update failed. First exception on row 0 with id a0DQ0000003vFohMAE; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = a0DQ0000003vFoh) is currently in trigger CRHUpdateWorkStatus, therefore it cannot recursively update itself:

 

Here is my trigger:

/* This trigger works based on if the "Request Approved" checkbox is checked.
If it is, it will update "Full-Time or Part-Time?" with the value in
"(Y) Full-Time or Part-Time?", provided that field is also not blank. */

trigger CRHUpdateWorkStatus on Church_Role_History__c (before update) {
     List<Church_Role_History__c> crhNEW = new List<Church_Role_History__c>();
     for(Church_Role_History__c crhOLD: Trigger.New)
     if (crhOLD.Request_Approved__c == True && crhOLD.Y_Full_Time_or_Part_Time__c != '')
     {
          crhNEW.add(new Church_Role_History__c (
          
          // Id
          id = crhOLD.Id,
          
          // Status
          Full_Time_or_Part_Time__c = crhOLD.Y_Full_Time_or_Part_Time__c
          ));
     }
     update crhNEW;
}

 

 

My test class:

@isTest
     private class TESTCRHUpdateWorkStatus {
          public static testmethod void MyTest() {
     
     {
          
          //Create a Contact for this test class.
          Contact c = new Contact();
          c.FirstName = 'Stephanie';
          c.LastName = 'Arce';
          insert c;
          
          //Create an Account for this test class.
          Account a = new Account();
          a.Name = 'Test Church';
          insert a;
     
          //insert a Church Role History record related to the Contact and Account.
          Church_Role_History__c crh = new Church_Role_History__c ();
          crh.Church__c = a.Id;
          crh.Person__c = c.Id;
          crh.Y_Full_Time_or_Part_Time__c = 'Full-Time';
          crh.Church_Position_Title__c = 'Administrative Assistant';
          crh.Request_Approved__c = True;
          insert crh;
          
          //Update the same Church Role History record so Request Approved = True.
          Church_Role_History__c crhu = [select Id from Church_Role_History__c where Id = :crh.Id];
          crhu.Request_Approved__c = True;
          update crhu;
          //See if "(Y) Full-Time or Part-Time?" value was copied to "Full-Time or Part-Time?"
          Church_Role_History__c crhq = [select Id from Church_Role_History__c where Id = :crhu.Id];
          system.assertEquals(crhq.Full_Time_or_Part_Time__c, 'Full-Time');
     }
   }
 }

 

Can someone explain the error message to me and what I have wrong in my trigger? Thank you so much for any help!

Best Answer chosen by Admin (Salesforce Developers) 
Jake GmerekJake Gmerek

In a nutshell you do not need the update statement at the end of your trigger. The Trigger is a 'before' trigger so it is running before the update occurs and by calling update you are updating the same record twice at the same time. You can also remove all the code in your if statement one line.  Here is how your trigger should look:

 

trigger CRHUpdateWorkStatus on Church_Role_History__c (before update) {
  for(Church_Role_History__c crhOLD: Trigger.New)
  {
    if (crhOLD.Request_Approved__c == True && crhOLD.Y_Full_Time_or_Part_Time__c != '')
    {
      crhOLD.Full_Time_or_Part_Time__c = crhOLD.Y_Full_Time_or_Part_Time__c
    }
  }
}

 The field that you are updating will be saved in the normal course of operations.

All Answers

Jake GmerekJake Gmerek

In a nutshell you do not need the update statement at the end of your trigger. The Trigger is a 'before' trigger so it is running before the update occurs and by calling update you are updating the same record twice at the same time. You can also remove all the code in your if statement one line.  Here is how your trigger should look:

 

trigger CRHUpdateWorkStatus on Church_Role_History__c (before update) {
  for(Church_Role_History__c crhOLD: Trigger.New)
  {
    if (crhOLD.Request_Approved__c == True && crhOLD.Y_Full_Time_or_Part_Time__c != '')
    {
      crhOLD.Full_Time_or_Part_Time__c = crhOLD.Y_Full_Time_or_Part_Time__c
    }
  }
}

 The field that you are updating will be saved in the normal course of operations.

This was selected as the best answer
Stephanie_ArceStephanie_Arce

That makes so much sense, thank you!