OK here is a real fun one.
I need to write tests that cover code that queries for custom metadata types. The code and test will be deployed to many different salesforce organizations which will contain entirely different records of this custom metadata.
The non-test code is querying the real custom metadata, but I need to test with all possible versions of the custom metadata, not just the records that actually exist. I need to do this for code coverage, error handling, and also so that I can deploy the same code across multiple organizations.
You can Instantiate Custom Metadata Types in Apex, but this does not help, because my code is querying the real custom metadata records, and it does not recognize records that I instantiate in memory in the test class.
I have seen the technique of using properties to store custom metadata values, but I can't see a way to apply that to this scenario.
public class DOMapUtil {
public static Map<String, String> DOtoNoReply = new map <String, String>();
public static Map<String, String> DOtoAdmEmail = new map <String, String>();
public static Map<String, String> DOtoProgName = new map <String, String>();
public static Map<String, String> DOtoSchoolName = new map <String, String>();
public static Map<String, String> DOtoUnivName = new map <String, String>();
public static Map<String, String> DOtoOARS = new map <String, String>();
public static List<Map<String, String>> CreateDOMaps(){
List<Map<String, String>> DOMaps = new List<Map<String, String>>();
for(Degree_Offering__mdt DegOff : [SELECT MasterLabel,
No_Reply_Email__c,
Admissions_Email__c,
Program_Name__c,
School_Name__c,
University_Name__c,
OARS_Endpoint__c
FROM Degree_Offering__mdt]) {
DOtoNoReply.put(DegOff.MasterLabel, DegOff.No_Reply_Email__c);
DOMaps.add(DOtoNoReply);
DOMaps.add(0,DOtoNoReply);
DOtoAdmEmail.put(DegOff.MasterLabel, DegOff.Admissions_Email__c);
DOMaps.add(1,DOtoAdmEmail);
DOtoProgName.put(DegOff.MasterLabel, DegOff.Program_Name__c);
DOMaps.add(2,DOtoProgName);
DOtoSchoolName.put(DegOff.MasterLabel, DegOff.School_Name__c);
DOMaps.add(3,DOtoSchoolName);
DOtoUnivName.put(DegOff.MasterLabel, DegOff.University_Name__c);
DOMaps.add(4,DOtoUnivName);
DOtoOARS.put(DegOff.MasterLabel, DegOff.OARS_Endpoint__c);
DOMaps.add(5,DOtoOARS);
}
return DOMaps;
}
Test class:
@IsTest
public class PayPalTest {
@TestSetup
public static void CreateOpps(){
List<Opportunity> Opps = new List<Opportunity>();
String DegOff = [SELECT MasterLabel FROM Degree_Offering__mdt].get(0).MasterLabel;
/*Degree_Offering__mdt DegOff = new Degree_Offering__mdt(MasterLabel='jsf-xyz',
Admissions_Email__c = 'SupaChill@admissions.com',
No_Reply_Email__c = 'noreply@2u.com',
Program_Name__c = 'JSF@Harvard',
School_Name__c = 'JSF School of Awesome',
University_Name__c = 'JSF University',
OARS_Endpoint__c = 'http://requestbin.net/r/tu1n40tu')*/
for (Integer i=0; i<1; i++){
Opportunity Opp = new Opportunity(Name = 'Opp', Degree_Offering__c = DegOff, StageName = 'Prospecting', CloseDate = date.today(),
Email_Address__c = 'test@2u.com'
);
Opps.add(Opp);
}
insert Opps;
}
@IsTest
public static void UpdateOpps(){
List<Opportunity> UpdatedOpps = [SELECT ID FROM Opportunity];
for (Opportunity Opp : UpdatedOpps){
Opp.Application_Fee_Waiver_Decision__c = 'Approved';
Opp.Application_Fee_Status__c = 'Paid Electronically';
Opp.Intent_To_Enroll__c = 'Enrolled';
Opp.Enrollment_Deposit_Status__c = 'Paid Electronically';
}
update UpdatedOpps; //Needs to run outside start/stop test to prevent uncommitted work error
Test.startTest();
OARSCalloutMock Mock = new OARSCalloutMock();
Test.setMock(HttpCalloutMock.class, Mock); ////Needs to run in start/stop test to prevent uncommitted work error
Test.stopTest();
Integer invocations = Limits.getEmailInvocations();
system.debug('Email invocations = '+ invocations);
system.assertEquals(3, invocations);
system.debug('Mock.callouts = '+ Mock.callouts);
system.assertEquals(2, Mock.callouts); //Won't work unless Test.setMock callout is run synchronously
}
String DegOff only queries existing meta-data records, and instantiating Degree_Offering__mdt DegOff does not create something that can be queried by the public class DOMapUtil.
Not an easy one to explain, hit me up with any questions. Thanks for any thoughts!