0

i have a Trigger class with metadata and i want to make a test class, but i don't know how i do with custom metadata. The custom metadata is a list that automatically adds member status to each campaign depending on its record type

Who can help me ? I have created a test class but it doesn't work and i know.

TRGHDL_Campaign_Member_Status

public with sharing class TRGHDL_Campaign_Member_Status extends TriggerHandler{

    Map<Id, Campaign> mcs = new Map<Id, Campaign>();
    Integer campaignStatusEmailOrder = 0;
    Map<Id, Id> recordTypeIdbyCampaignId = new Map<Id, Id>();
    List <CampaignMemberStatus> lstMemberStatus = new List<CampaignMemberStatus>();
    Id recordTypeEmail;
    Id recordTypeMarketing;

    public override void bulkAfter(Sobject[] newSoList,Map<Id,SObject> oldSoMap){
        recordTypeMarketing = Schema.SObjectType.Campaign.getRecordTypeInfosByDeveloperName().get('AM_Campagnes_evenements_marketing').getRecordTypeId();
        recordTypeEmail = Schema.SObjectType.Campaign.getRecordTypeInfosByDeveloperName().get('AM_Campagne_mass_email').getRecordTypeId();

        if(Trigger.isInsert){
            Set<Id> campaignIds = new Set<Id>();
            for(SObject so : newSoList){
                if (so.get('Id') != null){
                    campaignIds.add((Id)so.get('Id'));
                    recordTypeIdbyCampaignId.put((Id)so.get('Id') , (Id)so.get('RecordTypeID'));

                }
            }
            System.debug(recordTypeIdbyCampaignId);
        }
    }

    public override void afterInsert(SObject so){

        if (recordTypeIdbyCampaignId.get((Id)so.get('Id')) == ''){
            lstMemberStatus.addAll(getListMemberStatusMarketing(so.Id));
        }
        if (recordTypeIdbyCampaignId.get((Id)so.get('Id')) == ''){
            lstMemberStatus.addAll(getListMemberStatusEmail(so.Id));
        }
    }
        


    public static List<CampaignMemberStatus> getListMemberStatusMarketing (Id campagneId){

        List<AM_Statut_de_campagne_marketing__mdt> mcs = AM_Statut_de_campagne_marketing__mdt.getAll().values();
        List<CampaignMemberStatus> cms = new list<CampaignMemberStatus>();
        
        for (AM_Statut_de_campagne_marketing__mdt mc : mcs){
            CampaignMemberStatus ms = new CampaignMemberStatus();
            ms.CampaignId = campagneId;
            ms.Label = mc.label;
            ms.SortOrder = (Integer)mc.AM_SortOrder__c;
            cms.add(ms); 
        }
        return cms;
    }


    public static List<CampaignMemberStatus> getListMemberStatusEmail (Id campagneId) {
        
        List<AM_Statut_de_campagne_email__mdt> mcs = AM_Statut_de_campagne_email__mdt.getAll().values();
        List<CampaignMemberStatus> cms = new list<CampaignMemberStatus>();
        
        for (AM_Statut_de_campagne_email__mdt mc : mcs){
            CampaignMemberStatus ms = new CampaignMemberStatus();
            ms.CampaignId = campagneId;
            ms.Label = mc.Label;
            ms.SortOrder = (Integer)mc.AM_SortOrder__c;
            cms.add(ms); 
        }
        return cms;
    }
}

AM_TRGHDL_Campaign_Member_Status_TEST

@isTest
public with sharing class AM_TRGHDL_Campaign_Member_Status_TEST {
    private static String TU_PREFIX = 'TRGHDL_Campaign_Member_Status';


    @TestSetup
    static void makeCampaign() {

        id recordTypeMarketing = Schema.SObjectType.Campaign.getRecordTypeInfosByDeveloperName().get('AM_Campagnes_evenements_marketing').getRecordTypeId();
        id recordTypeEmail = Schema.SObjectType.Campaign.getRecordTypeInfosByDeveloperName().get('AM_Campagne_mass_email').getRecordTypeId();

        Campaign testcampagne1 = AM_DataFactory_TEST.genCampaign(TU_PREFIX + 'testcampagne1', null);
        testcampagne1.RecordTypeId = recordTypeMarketing;
        Campaign testcampagne2 = AM_DataFactory_TEST.genCampaign(TU_PREFIX + 'testcampagne2', null);
        testcampagne2.RecordTypeId = recordTypeEmail;

        insert new List <Campaign> {testcampagne1, testcampagne2};



    }

    @isTest
    static void TEST_TRGHDL_Campaign_Member_Status_Marketing (){

        Campaign testcampagne1 = [SELECT Name, Id FROM Campaign WHERE Name =:TU_PREFIX + 'testcampagne1'];
        List <CampaignMemberStatus> lstMemberStatus = new List<CampaignMemberStatus>();
        List <Campaign> lstCampaign = new List <Campaign> ();

        Campaign testCampaign = new Campaign();

        testCampaign.Name = 'nouveau';
        insert testCampaign;
        lstCampaign.add(testCampaign);

    }
}
1
  • Welcome to SFSE. Please take a moment to read How to Ask and take the tour. Please edit your post to include more detail about "it doesn't work". Are you getting error messages? What do you expect to get and what are you getting instead? Please edit your post. Sep 13, 2022 at 16:22

1 Answer 1

2

Custom Metadata Type records (i.e. records for objects that end in __mdt) are metadata, and thus you have access to whatever records you have for that Custom Metadata Type in the org that you're executing the test in.

If you're trying to deploy this to a new org, then you'll also need to deploy the Custom Metadata Type and its records. __mdt records, being metadata, can't be inserted (or rather, deployed) in a test, so you need to ensure that there is at least one __mdt record in the org where you're executing this test.

The alternative to this is to make and use a proxy class to act as, well, a proxy between the code that wants to use the Custom Metadata Type, and the Custom Metadata Type itself. Adding that layer of abstraction would allow you to create an in-memory instance of your __mdt record in your test, and to have it used in the code being tested.

A template for such a proxy class would be

public with sharing class MyMetadataProxy{
    private static List<My_Metadata__mdt> metadata = new List<My_Metadata__mdt>();
    private static Boolean useProvidedData = false;

    // This method is what allows us to craft in-memory instances in tests
    public static void setMetadata(List<My_Metadata__mdt> providedData){
        if(providedData != null){
            metadata = providedData;
        }

        useProvidedData = true;
    }

    public static List<My_Metadata__mdt> getAll(){
        // The purpose of this IF is to make the proxy "transparent" to its
        //   clients.
        // Fetches (and caches on the heap) the actual metadata type records
        //   in an org if we haven't previously called setMetadata() in this
        //   transaction.
        if(metadata.isEmpty() && !useProvidedData){
            metadata = My_Metadata__mdt.getAll().values();
            useProvidedData = true;
        }

        return metadata;
    }
}

You'd use in in your code like so

List<AM_Statut_de_campagne_marketing__mdt> mcs = MyMetadataProxy.getAll();

And you'd create an in-memory test metadata record like so

MyMetadataProxy.setMetadata(new List<My_Metadata__mdt>{
    new My_Metadata__mdt(field1__c = 'value 1', field2__c = 'value2')
};

Yes, the getAll() method returning a List instead of a Map breaks the expectation of the metadata type "interface", but names are easy enough to change if that's an issue for you.

1
  • 1
    the Proxy solution is the way to go because it allows for test isolation. Relying on org CMDT is a recipe for failed tests at unexpected times.
    – cropredy
    Sep 13, 2022 at 21:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .