Skip to main content
2 of 4
added 978 characters in body
Daniel Ballinger
  • 103.1k
  • 40
  • 275
  • 601

My understanding of the problem is that you want to be able to define the results of the following line in the trigger from the test methods:

 Boolean enableHandler = AccountTriggerCheckDisabled.IsHandlerDisabled(accountType, customMetadataField);

I assume the class looks something like:

public class AccountTriggerCheckDisabled {
    public static boolean IsHandlerDisabled(Schema.SObjectType classType, string customMetadataField) {
        // Query the CMDT based on the params and return a boolean
        return true;
    }
}

There are two ways to do this from a test method.

  1. The Hacky Way ===

At this risk of ire Kevin Poorman you could just hack something into AccountTriggerCheckDisabled that lets the test class control the response directly.

public class AccountTriggerCheckDisabled {
    // This would need to be keyed by the Schema.SObjectType as well.
    // I'm only using the string to make this example quicker.
    private Map<string, boolean> testResponse = new Map<string, boolean>();

    @TestVisible
    private static void defineTestResponse(Schema.SObjectType classType, string customMetadataField, boolean response) {
        testResponse.put(customMetadataField, response);
    } 

    public static boolean IsHandlerDisabled(Schema.SObjectType classType, string customMetadataField) {

        if(Test.isRunningTest() && !testResponse.isEmpty()) {
            if(testResponse.containsKey(customMetadataField)) {
                return testResponse.get(customMetadataField);
            }
        }

        // Query the CMDT based on the params and return a boolean
        return true;
    }
}

Now your test class can define the response from IsHandlerDisabled as required without even touching the CMDT.

@isTest
public class TriggersTurnedOff_Test {     
    @isTest
    public static void AreTheTriggersTurnedOff(){
        boolean mockTestResponseYouWantForTheTest = true; AccountTriggerCheckDisabled.defineTestResponse(Schema.Account.sObjectType, 'Disable_Account_c_AU__c', mockTestResponseYouWantForTheTest);

        //Now update an Account
       
        // When the trigger fires enableHandler will come back as true
    }
}
  1. The more complicated but overall better way. ====

Apex now has System.StubProvider for scenarios just like this one. It is more complicated to implement, but it essentially allows you to define an Apex class that will stand in for the actual AccountTriggerCheckDisabled class in the test context. This stub class can return whatever you want when the test is running.

You can see an example of this in Month of Testing: Advanced Topics in Salesforce Unit Testing (Part 3 of 3) under the Stubbing: with great flexibility comes great architecture heading.

Why is this approach better? The short answer is you don't need to have code specific to testing the class in the target class itself.

It is more complicated as you will need a mechanism to swap out the actual AccountTriggerCheckDisabled class with your stub class.

Daniel Ballinger
  • 103.1k
  • 40
  • 275
  • 601