Another way to handle this would be to make a proxy class that is responsible for accessing Custom Metadata Type records (instead of accessing them directly). Having this additional layer gives you the flexibility to make/use in-memory records of your __mdt
object (which because they're metadata, we can't insert/update in a test class). As a simple example of such a proxy class (which you will need to modify).
public class MyMDTProxy{
private static Map<String, MyMDTType__mdt> mdtRecordsByDeveloperName;
// This is a static initialization block, which we can basically think of as
// a "static constructor"
static{
mdtRecordsByDeveloperName = new Map<String, MyMDTType__mdt>();
// This step doesn't need to be done here, but you do need a way to get the
// "actual" MDT records somewhere in the proxy for it to be useful outside
// of unit tests.
// Making this a separate line (instead of just using this to initialize the
// map in the first place) helps guard against situations where you don't have
// any records for the MDT in your target org
mdtRecordsByDeveloperName.putAll(MyMDTType__mdt.getAll());
}
public static void addRecord(MyMDTType__mdt givenRecord){
mdtRecordsByDeveloperName.put(givenRecord.DeveloperName, givenRecord);
}
public static MyMDTType__mdt getInstance(String developerName){
return mdtRecordsByDeveloperName.get(developerName);
}
}
Usage would be basically the same as what you have now
// instead of Trigger_Disabler__mdt
if (TriggerDisablerProxy.getInstance('Account_Disabler')?.Disable_Trigger__c == true){
And setting this up in your test class is simple
// Since Salesforce clears out static variables between each test, we can't
// do this in an @SetupTest annotated method.
// It just needs to be a static method that gets called in each test method
static void mdtSetup(Boolean enabled){
// Because we're internally using a map and initializing with existing MDT
// records first, you can easily "override" the MDT record for tests
TriggerDisablerProxy.addRecord(new Trigger_Disabler__mdt(
DeveloperName = 'Account_Disabler',
Disable_Trigger__c = enabled
);
}
@isTest
static void triggerDisabled_doNoWork(){
mdtSetup(false);
insert new Account();
}
@isTest
static void triggerEnabled_doWork(){
mdtSetup(true);
insert new Account();
}
This is more work than Adrian's approach of using a @TestVisible
variable in a handler class.
In either approach though, you do want to make sure that you're keeping as much logic out of your actual trigger as possible.
else
isn't needed here. Areturn
immediately goes back to the next level up in the stack, which in this case would terminate the trigger. Also, if you've never heard of YAGNI (You Ain't Gonna Need It), this trigger only has one event, so you don't need to check if you're in that event. Best to wait until you know you're going to need it before you add it in.