Skip to main content
3 of 3
Mention StubProvider alternative approach
Phil W
  • 38.2k
  • 5
  • 53
  • 106

Our approach is to make sure unit tests don't use actual data but always use test data. Since Apex cannot control custom metadata instances, and those on the org are accessible in unit tests you need to avoid actually querying this data. Thus:

  • Use non-static methods, so we can mock out or override behaviour in unit tests
  • Make the methods we need to mock/override virtual
    • Split out data loading into separate virtual methods to allow this to be mocked
  • Use in-test-class specializations to drive specific behaviours

So, for example, your main code might be like:

public with sharing virtual class Xyz {
    public void myMethod(String name) {
        List<Abc__mdt> settings = loadSettings(name);

        if (settings.isEmpty() || !settings[0].Value__c.isNumeric()) {
            String error = 'Custom error message';
            throw new ElisaOCServiceException(error);
        }
    }

    protected virtual List<Abc__mdt> loadSettings(String name) {
        return [
            SELECT DeveloperName, Value__c
                FROM Setting__mdt
                WHERE DeveloperName = :name
        ];
    }
}

Then in your unit tests do something like:

@IsTest
class XyzTest {
    class TestXyz extends Xyz {
        private String theJSON;

        public TestXyz(String theJSON) {
            this.theJSON = theJSON;
        }

        protected override List<Abc__mdt> loadSettings(String name) {
            if (String.isBlank(theJSON) || String.isBlank(name)) {
                return null;
            } else {
                return (List<Abc__mdt>) JSON.deserialize(theJSON, List<Abc__mdt>.class);
            }
        }
    }

    @IsTest
    void testNoValidMDTsThrowsException() {
        Xyz testInstance = new TestXyz(null);

        try {
            testInstance.myMethod(null);

            System.assert(false, 'Should have had an exception');
        } catch (ElisaOCServiceException e) {
            // The expected situation
        }
    }

    ...
}

Note that if you use non-static methods you could also leverage the Apex mocking facilities, which avoids the need for virtuals, but still requires you to structure your code to make it testable. See mocking with the StubProvider for details.

Phil W
  • 38.2k
  • 5
  • 53
  • 106