/sfdx-apex-truths

Truths about how Apex and other automation features work on the Salesforce Platform

Primary LanguageApex

Salesforce Apex Truths

The code and configuration in this project exist to validate both expected and unexpected behavior with Salesforce Apex. Each truth will be documented in this README with a brief explanation of the objects, triggers and other components used to validate the truth.

As a starting point, see the "Triggers and Order of Execution" page in the Apex Developer Guide.

Truth 1

Workflow rules are only evaluated once during a DML operation, even when a Lightning process updates the same record

Let's say you have a workflow rule that always runs on create and edit events, and the workflow rule performs a field update.

Normally when a field update touches a record, triggers on that object are executed a second time. If a Lightning process then updates the record, you would expect triggers to execute once more, followed by the field update, followed by a final, fourth round of trigger executions, right?

But in reality the fourth round of trigger executions never occur, and neither does the second field update. Such is this first Apex truth.

To verify this behavior, consider the following chain of events.

  1. User creates an Apex Truth 1 record
  2. ApexTruth1Trigger detects the before insert event and executes
  3. ApexTruth1Trigger detects the after insert event and executes again
  4. The Set Rerun workflow rule sets Rerun to true
  5. ApexTruth1Trigger detects the before update event and executes. The trigger resets IsRerun__c to false.
  6. ApexTruth1Trigger detects the after update event and executes again
  7. The ApexTruth1CapitalizeName Lightning process executes, updating the record
  8. ApexTruth1Trigger detects the before update event and executes for the fifth time
  9. ApexTruth1Trigger detects the after update event and executes again for the sixth time

Each time ApexTruth1Trigger executes it creates a log entry for each Apex Truth 1 record being processed.

At the conclusion of this chain of events, we have the following.

  • An Apex Truth 1 record with a capitalized name
  • 1 orphaned Log Entry record from the before insert trigger execution
  • 5 Log Entry records under the Apex Truth 1 record
  • Rerun showing false on the Apex Truth 1 record

Run ApexTruth1Test to confirm these outcomes.

Truth 2

The overridden method in a subclass is always executed when invoked, even when the subclass instance is cast as the superclass

Let's say you want to create a subclass, maybe to help with Apex unit tests. Regardless of the reason, you want to know with certainty: If the subclass instance is cast as the superclass, does the overridden method in the subclass still get executed when called?

The ApexTruth2MegaserviceTest.getName test proves that the overridden method in the subclass is always executed, even when the subclass instance is explicitly cast as the superclass.

Truth 3

Static variables persist throughout the execution of an Apex test method, even in the resolution of asynchronous platform event triggers

If you're using static variables to hold service registries or other mutable data that you expect to persist within a single Apex transaction, you will want to know for sure how these static variables can be set and staged for Apex tests.

ApexTruth3HelloTriggerTest and ApexTruth3HelloEventTriggerTest together prove that static variables persist before and after the point when either Test.startTest() or Test.stopTest() is called. Furthermore, even though the platform event trigger executes in a special asynchronous context as Automated Process, the static variable still persists such that any interactions with the static variable made by Automated Process can be validated after Test.stopTest().