0

I have a trigger recursion class to try and stop trigger recursion:

public class checkRecursive {

private static set<id> alreadyProcessed = new set<id>();

public static boolean runOnce(list<sObject> records){
boolean run = true;
for(sObject obj:records){
   ID objID = (ID)obj.get('ID');
   System.Debug('ObjID: ' + objID + ' ap: ' + alreadyProcessed);
   if(objID != null && !alreadyProcessed.contains(objID)){
      alreadyProcessed.add((ID)obj.get('ID'));
   }else{
    if(ObjID != null){
      run = false;
    }
   }
}
return run;
}

}

With this code in the trigger

if(checkRecursive.runOnce(Trigger.New)){
    new Triggers()
    .bind(Triggers.Evt.beforeUpdate, new Account_ChangeOwnerTrigger())
 .manage();     
    }
}

This is the test method:

@isTest static void whenChangingBUValidateAssigmentDateUpdated(){

Account testAccount = [Select ID, Business_Unit__c, BU_Assignment_Date__c from Account limit 1];
    Business_Unit__c BU1 = [Select ID From Business_Unit__c where Name = 'Test BU' limit 1];
    Business_Unit__c BU2 = [Select ID From Business_Unit__c where Name = 'Test BU 2' limit 1];
    //set BU which should set date
    testAccount.Business_Unit__c = BU1.id;
    System.Debug('Update 1');
    update testAccount;
    //Reset date
    testAccount.BU_Assignment_Date__c = System.Today().AddDays(-2);
    System.Debug('Update 2');
    update testAccount;

    testAccount = [Select ID, Business_Unit__c, BU_Assignment_Date__c from Account limit 1];
    //not part of this test but need to validate that the date is not today to know for sure if it changes when setting the new bu
    System.assertNotEquals(testAccount.BU_Assignment_Date__c,System.Today());

    Test.startTest();
        testAccount = [Select ID, Business_Unit__c, BU_Assignment_Date__c           from Account limit 1];
        testAccount.Business_Unit__c = BU2.Id;
        System.Debug('Before test Account Update');
        update testAccount;
        System.Debug('After test Account Update');
    Test.stopTest();

    testAccount = [Select ID, BU_Assignment_Date__c from Account limit 1];
    System.assertEquals(testAccount.BU_Assignment_Date__c,System.Today());
}

What seems to be happening from the debug logs is that the multiple updates in the test class are not resetting trigger context and it thinks it's recursion:

Debug Log

The second pass through the checkRecursive is true, it's a workflow. Not sure why the ID is in the set once the second and third updates are done. Is should be resetting for each update call?

  • Just as a test I tried adding a System.RunAs inside the start test call. Still seems to be failing. – user4978 Feb 15 '17 at 21:47
0

As soon as I posted it I found the answer. I needed to add a method to reset the list

Public static void resetList(){
    alreadyProcessed = new set<id>();
}

I call that before each update in the test class to manually reset.

| improve this answer | |
  • It's cool that you figured it out, but this isn't a scaleable solution .. rip whoever has to work on this next – EricSSH Feb 15 '17 at 22:23
  • Actually its only an issue with SF test classes. In production it would reset properly as you won't be doing multiple updates to the same record within the same process. That only happens in tests. – user4978 Feb 17 '17 at 21:49
  • Oh it's in your trigger frame work? Then you should put that method in your framework, so it's easily called – EricSSH Feb 17 '17 at 22:14
  • Yeah you're right, the trigger framework needs to be fixed. The code needs to move to the handlers not the trigger. – user4978 Feb 20 '17 at 16:41

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.