Test Data for Custom Metadata in Apex Test Class

Create Test Data for Custom Metadata in Apex Test Classes 

Introduction 

Since Summer’15 Release, Custom Metadata is generally available in Salesforce. The introduction of Custom Metadata brought various benefits over List Custom Settings in order to store the configuration data which could be utilized from your apps in your org. 

While deploying Custom Metadata from one org to another, you can choose which records you can move across in the deployment. This I believe is one of the key benefits of Custom Metadata over List Custom Settings. However, the limitation is you can’t create/update the Custom Metadata records using Apex. It’s metadata of course. How can you? 

Challenge 

The issue with Custom Metadata, is unlike List Custom Settings, Salesforce does not allow you to create test data for Custom Metadata. 

Does that mean, you depend on your org’s Custom Metadata configuration records while running the tests or deployment? I am sure, you won’t like that approach and surely will try to find a way to create test records somehow in your Apex test class. So, let’s not talk of the problems only. Read on to find the solution. 

Needful in the Apex Class 

When you’re referencing Custom Metadata in your Apex Class (not Apex Test Class. We’ll talk about referencing them in Apex Test Class shortly), you’re required to access the Custom Metadata using properties (get; set;).  

E.g. Below diagram shows the Custom Metadata definition from the org followed by the code snippet illustrating the way it should be referenced in your Apex Class. 

Fig.1 Snapshot of Custom Metadata created in Salesforce 

@testVisible static List<Sandbox_Refresh_Mapping__mdt> sandboxRefreshMappings
get
    if(sandboxRefreshMappings == NULL){ 
        sandboxRefreshMappings =
[SELECT Field_Name__c, SObject_Name__c, Masking_Value__c FROM         Sandbox_Refresh_Mapping__mdt]; 
    } 
    return sandboxRefreshMappings

set

Code Snippet to reference any Custom Metadata in your Apex Class 

You may consider this step as best practice or recommended approach to reference the Custom Metadata in your apex class. As this will make your life easy in terms of creating custom metadata in Apex Test.  

Note: You need not to keep the property private. This is just an illustration. 

Create Test Data 

Phew… Now we are talking. Last but not the least, creating the test custom metadata records in test class. 

If you try to create test records for custom metadata in a conventional manner, obviously it would be disappointing to see the errors. 

The simple way is to create a JSON structure for the fields in the Custom Metadata for as many records you want to create in your test code and deserialize it. Simple? It is indeed.  

Just one thing to keep in mind while doing this. Create your Apex Class instance within Test.startTest() method only, otherwise your Custom Metadata property will be referenced outside of startTest() context as a result your org’s custom metadata will be referenced as opposed to that of your JSON structure, making the JSON structure useless.  

Please refer to the code snippet given below on how to create the JSON structure and deserialize it. 

public static testMethod void testCorrectObjectMapping(){

//Step 1: Deserialized Custom Metadata instance. (Test Records) 
List<Sandbox_Refresh_Mapping__mdt> testSandboxRefreshMappings = (List<Sandbox_Refresh_Mapping__mdt>)Json.deserialize('[{"SObject_Name__c": "Account","Field_Name__c": "Phone","Masking_Value__c" : "867"},{"SObject_Name__c": "Contact","Field_Name__c": "Email","Masking_Value__c" : ".invalid"},{"SObject_Name__c": "Contact","Field_Name__c": "Phone","Masking_Value__c" : "867"}]', List<Sandbox_Refresh_Mapping__mdt>.class); 
 

//Step 2
Test.startTest();
//Assign Test Records created above to the class property
SandboxRefreshBatch.sandboxRefreshMappings = testSandboxRefreshMappings;

//Create Class instance and proceed further with your testing
Database.executeBatch(new SandboxRefreshBatch());
Test.stopTest();
}

Limitations 

One limitation of this approach that I can see is creating the instance of the Apex Class with Test.startTest() block. There can be use cases where you need to create the instance of the Apex Class before Test.startTest() block. In such cases, this approach may not work. 

4 thoughts on “Test Data for Custom Metadata in Apex Test Class”

Leave a reply to Sushanth Cancel reply