3

I've got an issue with some managed package test classes (specifically CPQ test classes), where I'm running into SoQL limits when certain test classes execute. What I'd like to do is disable certain triggers when the test class originates from the managed package.

Is there a way to access/identify the namespace prefix of the class that initiated the process programatically in order to disable triggers from firing?

0

One of the approaches that I could think of is to utilize sort of a "marker interface" which determines if the trigger needs to be executed or not based on a flag. In any case, you need to handle this within your trigger logic even if you are able to identify the context of the running trigger. It's more a design choice how you will want to achieve this, but something as below will work in such cases.

Let's say I define a simple class as:

public class IMarkerInterface {
    public static Boolean RUN_TRIGGER = false;
}

And in my trigger, I would use this class to branch the execution logic something as:

if(IMarkerInterface.RUN_TRIGGER == false) {
    // skip
} else {
    // execute the logic
}

Now for all my test class written, I would have set this flag to true IMarkerInterface.RUN_TRIGGER = true; in my test methods, so that all my local test classes will always execute this logic.

The ones from managed package will always skip the trigger logic, because they would not have had set this value.

0

You can inspect the stack trace, for one. That might look like:

List<String> stackTrace = new DmlException().getStackTraceString().split('\n');

It should be easy enough to parse out the namespace from each line. I think you'd just need to check substringBefore('.') or substringBefore('__'). Hard for me to check right now since I don't have any such packages installed currently.

  • The stack trace doesn't go beyond the current trigger context, actually. I'm not sure why it's designed that way, but that's how it works. – sfdcfox May 15 '18 at 14:48
0

If you know the name of the class , you can obtain namespace prefix with a SOQL like below

ApexClass cs =[select NamespacePrefix from ApexClass where Name =:'<name of the class from your package>'];
          String nameSpacePrefix= cs.NamespacePrefix;
0

Unfortunately, there's no way to detect the parent context in a trigger. Every time you enter a trigger context, the previous heap and stack is "set aside", so that all you can see is your own execution context. I explored this concept more in this answer if you're interested in further reading. My recommended approach if you're concerned about this is to put in a dead-man-switch style in your trigger handler that must be explicitly set to true in order to run the trigger. This would make sure that you're only testing the trigger when you intend to. Something like this:

 public static Boolean skipTrigger = Test.isRunningTest();
 public void handleTrigger(...) {
     if(skipTrigger) {
         return;
     }
     ...

If you have a central testing utility, you can enable the triggers there as part of your startup routine:

public static void loadData() {
    SomeTriggerHandler.skipTrigger = false;
    ...
}

We have a framework like this because it standardizes our unit tests to all use the same data:

@isTest public class TestingFramework {
    // static variables to hold common test data here
    public static Account ...;
    public static Contact ...;
    ...
    // This is called from a @testSetup method in each unit test class
    // Note that we also skip the triggers here, too...
    public static void testSetup() {
        Test.startTest(); // Don't let testSetup eat your governor limits
        ...
    }
    // Load things we need to know during testing, like Record Type IDs.
    public static void initialize() {
        ...
    }
    static {
        initialize();
    }
    // Load data; this is called at start of each unit test
    public static void loadData() {
        SomeTriggerHandler.skipTrigger = false;
        ...
    }
    ...
}

Other possible methods are available as well, but the point is you can avoid running your triggers with some carefully designed programming choices.

  • 1
    Thanks to you both! I I think implementing Jayant Das' solution would be the easiest at this point, as we don't have a centralized testing utility (yet!!). I have a similar process in which a custom setting is used to avoid triggering service contract processes in a PB – Nathan Lee May 15 '18 at 15:12
  • 1
    @NathanLee Of course, you can use whichever works for you. We use this approach in our tests even though not all tests are converted over yet (but the triggers mostly are, but we default them on instead of off, because we're not fully converted yet). – sfdcfox May 15 '18 at 15:14
  • ,sfdcfox what do you guys think about this? salesforce.stackexchange.com/a/218154/19118 @JayantDas – Pranay Jaiswal May 15 '18 at 15:24
0

Why not use this (No Pun Intended)?

Whenever you call a trigger, an instance of that trigger is in memory. You can use it to your Advantage.

trigger UserTrigger on User (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
   System.debug(this);
}

Ouptput:

16:19:31:138 USER_DEBUG [4]|DEBUG|UserTrigger:[]
16:19:31:138 USER_DEBUG [4]|DEBUG|UserTrigger:[]

The same you can use for your debug. When running from namespace it also prints namespace name.

Unforutnely very basic documentation is available for this keyword. https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_keywords_this.htm

  • That's only true if the trigger is in the namespace. They're trying to figure out if they're being called from a namespace, which is not the same thing. – sfdcfox May 15 '18 at 15:28
  • It all depends on how you want to design. The best and recommended way is to have a kind of a framework in place. And if you say have test classes/methods follow that framework, you are in control. Ultimately with whichever approach you use, your branching logic still needs to be addressed in the trigger. – Jayant Das May 15 '18 at 15:29

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.