I've had success with mocking when testing interactions between configuration and code which are difficult to control. Consider a structure like the following:
public virtual class PortalMetadata
{
static PortalMetadata service = new PortalMetadata();
@TestVisible void setMock(PortalMetadata mock) { service = mock; }
public static List<MyMetadata__mdt> getAll() { return service.getAll(); }
protected virtual List<MyMetadata__mdt> getAll()
{
return [SELECT Portal_Url__c FROM MyMetadata__mdt];
}
}
Okay, so now you can mock out which records get returned, but how can you specify your own metadata records? Well, serialization has been a useful trick for me lately and comes in handy again here:
Map<String, Object> data = new Map<String, Object>
{
'Portal_Url__c' => 'someUrl'
};
MyMetadata__mdt metadataRecord = (MyMetadata__mdt)JSON.deserialize(
JSON.serialize(data), MyMetadata__mdt.class
);
How does the above help you test? Well, now you can set up your own mock metadata and have complete control over what gets "queried":
@IsTest
class testMyClass
{
static final String URL = 'some_url_here';
class PortalMetadataMock extends PortalMetadata
{
protected override List<MyMetadata__mdt> getAll()
{
Map<String, Object> data = new Map<String, Object> { 'Portal_Url__c' => URL };
return new List<MyMetadata__mdt>
{
(MyMetadata__mdt)JSON.deserialize(
JSON.serialize(data), MyMetadata__mdt.class
)
};
}
}
static testmethod void testGetLogoutUrl()
{
Test.startTest();
PortalMetadata.setMock(new PortalMetadataMock());
String retrievedUrl = MyClass.getLogoutUrl();
Test.stopTest();
system.assertEquals(URL, retrievedUrl, 'Assertion message here');
}
}
Hierarchy Custom Setting
if all you want to do is set an org default?