Can Custom Metadata Be Created in Test Classes?

Can Custom Metadata Be Created in Test Classes?

On February 16, 2025, Posted by , In Salesforce Technical Questions, With Comments Off on Can Custom Metadata Be Created in Test Classes?

Question:

I have three questions regarding using Custom Metadata in Salesforce test classes:

  1. Is there any way to create Custom Metadata records in test classes? I attempted to create them within a test class but encountered an error stating that the fields of the metadata are not writable.
  2. If Custom Metadata records cannot be created in test classes, does that mean we need to declare actual values in the Custom Metadata and use them in our test classes?
  3. If the second point is correct, does this imply that we must create the necessary Custom Metadata records in the environment where we are deploying our code before proceeding with the actual deployment?

CRS Info Solutions provides top-notch Salesforce training with real-time projects, certification guidance, interview coaching, and a practical, job-ready approach.

Answer:

Salesforce Technical Questions with Answers Apex, LWC, Marketing Cloud

Custom Metadata records cannot be created in test classes. This is an intentional design choice by Salesforce to maintain a clear distinction between metadata and data. Custom Metadata is primarily configuration information that is meant to be managed declaratively by administrators, not programmatically by developers within code. Allowing test classes to create or manipulate Custom Metadata would undermine this separation and could lead to unpredictable behavior in managed environments.

If you need to test behavior dependent on Custom Metadata, there are a few approaches you can take:

Approach 1: Use Real Custom Metadata Records

It involves leveraging actual Custom Metadata records in test classes by inserting them beforehand or using @testSetup methods. This ensures that the test class interacts with realistic data, validating behavior in real-world scenarios. However, Salesforce restricts direct creation in test methods, requiring the use of data loaded through setup methods or data imported prior to testing.

Example :

@testSetup
static void setupMetadata() {
    CustomMetadata__mdt metadataRecord = new CustomMetadata__mdt(
        DeveloperName = 'TestMetadata',
        MasterLabel = 'Test Label',
        Field1__c = 'Value'
    );
    insert metadataRecord;
}

@isTest
private class TestCustomMetadata {
    @isTest
    static void testWithRealMetadata() {
        CustomMetadata__mdt metadata = [SELECT Field1__c FROM CustomMetadata__mdt WHERE DeveloperName = 'TestMetadata' LIMIT 1];
        System.assertEquals('Value', metadata.Field1__c);
    }
}

Code explanation : The code demonstrates how to use real Custom Metadata records in test classes by setting them up with the @testSetup method, which inserts a CustomMetadata__mdt record. The test class TestCustomMetadata retrieves this record and validates that the Field1__c value is correctly stored. This approach ensures that tests interact with realistic metadata while complying with Salesforce’s restrictions on creating Custom Metadata directly in test methods.

Approach 2: Simulate Custom Metadata with a Wrapper Class

Simulating Custom Metadata with a wrapper class involves creating a custom Apex class that mimics the structure and behavior of Custom Metadata records. This allows developers to test logic that interacts with metadata without actually relying on real metadata records in Salesforce. By using mock data within the wrapper class, developers can ensure tests remain isolated and independent of actual metadata, while still validating business logic. Here’s an example:

Wrapper Class and Metadata Handler:

@testVisible
private static OrderConfigurationSetting setting {
    get {
        if (setting == null) {
            Order_Configuration_Settings__mdt metadata = [
                SELECT
                    Batch_Run_Frequency__c,
                    Duplicate_Day_Range__c,
                    Qty_Minimum__c
                FROM Order_Configuration_Settings__mdt
                WHERE DeveloperName = :DEFAULT_SETTING_NAME
            ];
            setting = new OrderConfigurationSetting(
                metadata.Batch_Run_Frequency__c,
                metadata.Duplicate_Day_Range__c,
                metadata.Qty_Minimum__c
            );
        }
        return setting;
    }
    set;
}

@testVisible
private class OrderConfigurationSetting {
    public String batchRunFrequency;
    public Integer duplicateDayRange;
    public Integer qtyMinimum;

    public OrderConfigurationSetting(
        String batchRunFrequency,
        Decimal duplicateDayRange,
        Decimal qtyMinimum
    ) {
        this.batchRunFrequency = batchRunFrequency;
        this.duplicateDayRange = Integer.valueOf(duplicateDayRange);
        this.qtyMinimum = Integer.valueOf(qtyMinimum);
    }
}

Code explanation : The code defines a lazy-loaded singleton property setting of type OrderConfigurationSetting, which retrieves values from a custom metadata type (Order_Configuration_Settings__mdt) when first accessed and caches the result. The OrderConfigurationSetting inner class stores configuration values and converts Decimal fields to Integer where necessary. The @testVisible annotation allows unit tests to access these otherwise private members for testing purposes.

OrderConfigurationSetting Class

@testVisible
private class OrderConfigurationSetting {
    public String batchRunFrequency;
    public Integer duplicateDayRange;
    public Integer qtyMinimum;

    public OrderConfigurationSetting(
        String batchRunFrequency,
        Decimal duplicateDayRange,
        Decimal qtyMinimum
    ) {
        this.batchRunFrequency = batchRunFrequency;
        this.duplicateDayRange = Integer.valueOf(duplicateDayRange);
        this.qtyMinimum = Integer.valueOf(qtyMinimum);
    }
}

Code explanation : The OrderConfigurationSetting class is a private Apex class with the @TestVisible annotation, making it accessible in test classes. It defines three public properties (batchRunFrequency, duplicateDayRange, and qtyMinimum) and a constructor that initializes them, converting Decimal inputs to Integer where needed.

Approach 3: Use Test-Specific Metadata

Using test-specific metadata involves creating mock or test-specific metadata records that mimic real metadata behavior without affecting the actual configuration. This can be achieved by using custom classes, static variables, or mock data in test methods, allowing for isolated and repeatable tests. This approach ensures that tests can run independently of the environment’s metadata, maintaining test integrity while avoiding the need to modify real metadata records.

Summing Up

Salesforce restricts the creation of Custom Metadata in test classes to maintain the distinction between metadata and data, ensuring consistent and stable configuration across environments. To work around this, developers can abstract metadata access into service layers, using mock data or static variables for testing purposes. This approach supports isolated testing, encourages maintainable code design, and avoids compromising metadata integrity.

Empower Your Career with Salesforce Training in New York

Elevate your professional journey with CRS Info Solutions’ top-rated Salesforce training, crafted to provide the skills and expertise required to excel in the ever-evolving Salesforce ecosystem. Our industry-focused courses span Salesforce Admin, Developer, and AI modules, blending in-depth theoretical knowledge with hands-on experience through practical, real-world projects.

With a strong emphasis on practical application, Salesforce training in New York, USA we offer personalized mentorship, detailed study resources, and expert-led certification preparation to fully equip you for success in interviews and beyond. Gain the confidence and skills to thrive in your Salesforce career.

Join our free demo class today and take the first step toward a rewarding future! Enroll now for a free demo!!!

Related Posts :

Comments are closed.