We have a trigger on Opportunity that updates the OpportunityLineItem when the Opportunity is won. We also have workflow rules on the OpportunityLineItem that fire and this causes some recursion to occur.
At the moment this doesn't cause any real problems but while looking at one of the approaches (static boolean class in combination with the trigger setting it once it's fired) – this works fine within the UI but we found the test methods no longer passed. It looks as though the triggers have already fired and the boolean has already been set to prevent further running.
The testmethod is too large to share on SFSE but basically inserts a number of Opportunities then updates the Stage so they are won. Without the CheckRecursive class they assert as expected with CheckRecursive the asserts fail as the triggers have not fired.
Is this a limitation of testmethods or something else I am missing?
Not sure if relevant but I am using test.StartTest() and test.StopTest() either side of the stage update in my test method:
Test.startTest();
update closeOptyList;
Test.stopTest();
Example Trigger:
trigger OptyDemo on Opportunity (before insert, before update)
{
if(CheckRecursive.RunMe)
{
Opty_Utils.someMethod(Trigger.New);
CheckRecursive.RunMe=false; //Prevent recursion
}
}
Example Recursive class:
public class CheckRecursive
{
public static boolean runME = true; //General use
}
Best Answer
this is a great question. We had similar issues for years. First of all the Recursive class is a great way to make sure that a trigger is executed once.
In your case the complexity has been increased by adding a workflow update. As described in the salesforce documentation "Triggers and Order of Execution" Workflow-Field-Updates can fire triggers again.
It's kind of important that the trigger will be executed only one more time.
In your case there is only one solution to make sure that a trigger is executed once: Remove all workflow updates and add the functionality to the existing trigger.
And btw. the usage of a Recursive class doesn't work as intended if you try to update more than 200 records at the same time. Salesforce will split the request in chunks of 200 records.
This behavior is indirectly documented:
However, in case of more than 200 records the trigger will be executed multiple times. (Once for each chunk of data.) However, the runMe variable will be reseted for each API batch, but the execution context stays the same, therefore it is still possible that you reach the api limits.