4

It says here that trigger context variables are contained in the System.Trigger class.

However, such a class is unknown to the Apex language reference, and Trigger doesn't seem to behave like a class either. For example, the expected property Trigger.class is inaccessible from Apex code.

Trigger context contents and usage is reasonably clear, but what exactly is Trigger?

Background: The idea of using a test stub in place of a real DML-fired trigger context came up while writing tests for a trigger handler class. I would first need to create a stub trigger context, and then execute my trigger in it. I'm yet to find a way to do that.

2 Answers 2

8

System.Trigger behaves as a final static variable of an unknown, or anonymous, class, that resides in the System namespace, which itself behaves much like a static final variable of an anonymous class. Namespaces work like they do in C#, in that they can contain both members and classes, but without an explicit Type that can be referenced, as a class would be referenced.

As a more direct answer to your question, System.Trigger can only be accessed in a trigger context, as it is always null otherwise, and furthermore has a private setter, so writing a test method requires constructing the necessary records to call a DML operation on. You can't fake trigger context. At least, not with any method I've tried.

Unfortunately, the language has very little reflection available, and isn't open source, so the best you can get from an outside developer like myself is a reasonably vague answer.

I would speculate that many standard features of the language are written using special exceptions that would make them impossible to replicate in the current language syntax.

When practical, write your methods to accept plain lists or maps, and use trigger variables from triggers, and custom lists or maps in test methods. This delegates trigger syntax to only triggers, and test methods can operate independently of the trigger variables.

4

While System.Trigger cannot be referenced outside of a trigger you can strip down the variables and pass them into your own class. Your own "wrapper" class can be passed around in your Apex functions.

public TriggerContext(Boolean isExecuting,
                      Boolean isInsert, 
                      Boolean isUpdate,
                      Boolean isDelete,
                      Boolean isBefore,
                      Boolean isAfter,
                      Boolean isUndelete,
                      List<SObject> newList,
                      Map<ID, SObject> newMap,
                      List<SObject> oldList,
                      Map<ID, SObject> oldMap,
                      Integer size){
    this.isExecuting = isExecuting;
    this.isInsert = isInsert;
    this.isUpdate = isUpdate;
    this.isDelete = isDelete;
    this.isBefore = isBefore;
    this.isAfter = isAfter;
    this.isUndelete = isUndelete;
    this.newList = newList;
    this.newMap = newMap;
    this.oldList = oldList;
    this.oldMap = oldMap;
    this.size = size;
}

And then in your trigger:

TriggerContext tc = new TriggerContext(Trigger.isExecuting,
                                       Trigger.isInsert,
                                       Trigger.isUpdate,
                                       Trigger.isDelete,
                                       Trigger.isBefore,
                                       Trigger.isAfter,
                                       Trigger.isUndelete,
                                       Trigger.new,
                                       Trigger.newMap,
                                       Trigger.old,
                                       Trigger.oldMap,
                                       Trigger.size);

Now you can pass around System.Trigger by passing TC to your Apex classes.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .