Improve performance of Dynamic Application Factories

Also added a method overload to provide a Package Name.
Useful for DX based second generation packages. Now each package can have their own bindings.
This commit is contained in:
wim
2023-09-01 15:39:25 +01:00
parent b658e6226b
commit a0fc1bd10d
22 changed files with 416 additions and 139 deletions
@@ -37,6 +37,7 @@ public virtual class fflib_AppBinding
protected System.Type implementationType { get; set; }
protected System.Type interfaceType { get; set; }
protected String namespacePrefix { get; set; }
protected String packageName { get; set; }
protected fflib_SharingMode sharingMode { get; set; }
public Integer compareTo(Object compareTo)
@@ -89,6 +90,14 @@ public virtual class fflib_AppBinding
return this.namespacePrefix;
}
/**
* @return Returns the Application Package Name for the binding
*/
public String getPackageName()
{
return this.packageName;
}
/**
* @return Returns the number of the order sequence in which the binding should be returned
*/
@@ -188,6 +197,19 @@ public virtual class fflib_AppBinding
return this;
}
/**
* Sets the Application Second Generation Package Name
*
* @param applicationPackageName The name of the 2GP package
*
* @return An instance of itself to enable method chaining
*/
public fflib_IAppBinding setPackageName(String applicationPackageName)
{
this.packageName = applicationPackageName;
return this;
}
/**
* Set the order number so that the resolver can sort the bindings.
* The higher the number, the more priority.
@@ -43,6 +43,7 @@ public with sharing class fflib_AppBindingMetaDataModule
.setImplementationType(getSystemType(binding, fflib_AppBinding__mdt.ImplementationType__c))
.setInterfaceType(getSystemType(binding, fflib_AppBinding__mdt.InterfaceType__c))
.setNamespacePrefix(binding.NamespacePrefix)
.setPackageName(binding.ApplicationPackage__r.DeveloperName)
.setSequence(binding.BindingSequence__c)
.setSharingMode(getSharingModeFromString(binding.SharingMode__c))
);
@@ -132,6 +132,11 @@ public virtual class fflib_AppBindingResolver
return this;
}
public fflib_IAppBindingResolver byPackageName(String packageName)
{
this.bindingToResolve.setPackageName(packageName);
return this;
}
/**
* Handles lazy loading of modules, if no custom module is configured (via addModule) the default module is returned
@@ -63,6 +63,67 @@ public virtual class fflib_AppBindings
}
}
public List<fflib_IAppBinding> getBindings()
{
return this.bindings;
}
public Map<Object, Type> getImplementationByBindingObject()
{
this.bindings.sort();
Map<Object, Type> result = new Map<Object, Type>();
for (fflib_IAppBinding binding : bindings)
{
Object bindingObject = binding.getBindingObject();
if (result.containsKey(bindingObject)) continue; // Skip bindings with lower sequence
result.put(bindingObject, binding.getImplementationType());
}
return result;
}
public Map<Type, Type> getImplementationByInterface()
{
this.bindings.sort();
Map<Type, Type> result = new Map<Type, Type>();
for (fflib_IAppBinding binding : bindings)
{
Type interfaceType = binding.getInterfaceType();
if (result.containsKey(interfaceType)) continue; // Skip bindings with lower sequence
result.put(interfaceType, binding.getImplementationType());
}
return result;
}
public Map<SObjectType, Type> getImplementationBySObjectType()
{
Map<SObjectType, Type> result = new Map<SObjectType, Type>();
for (fflib_IAppBinding binding : bindings)
{
Object bindingObject = binding.getBindingObject();
if (bindingObject instanceof SObjectType && result.containsKey((SObjectType) bindingObject) == false)
{
result.put((SObjectType) bindingObject, binding.getImplementationType());
}
}
return result;
}
public List<System.Type> getImplementations()
{
List<System.Type> result = new List<System.Type>();
for (fflib_IAppBinding binding : bindings)
{
result.add(
binding.getImplementationType()
);
}
return result;
}
public fflib_IAppBindings selectByObject(Object bindingObject)
{
if (null == bindingObject) return this;
@@ -149,21 +210,18 @@ public virtual class fflib_AppBindings
return new fflib_AppBindings(result);
}
public List<fflib_IAppBinding> getBindings()
public fflib_IAppBindings selectByPackageName(String packageName)
{
return this.bindings;
}
if (null == packageName) return this;
public List<System.Type> getImplementations()
{
List<System.Type> result = new List<System.Type>();
List<fflib_IAppBinding> result = new List<fflib_IAppBinding>();
for (fflib_IAppBinding binding : bindings)
{
result.add(
binding.getImplementationType()
);
if (binding.getPackageName() != packageName) continue;
result.add(binding);
}
return result;
return new fflib_AppBindings(result);
}
public List<Object> getObjects()
@@ -75,6 +75,7 @@ public virtual without sharing class fflib_AppBindingsSelector extends fflib_SOb
return (List<fflib_AppBinding__mdt>) Database.query(
newQueryFactory()
.selectField('ApplicationPackage__r.DeveloperName')
.selectField('BindingObject__r.QualifiedApiName')
.toSOQL());
*/
@@ -84,7 +85,9 @@ public virtual without sharing class fflib_AppBindingsSelector extends fflib_SOb
'SELECT {0} FROM {1}',
new List<String>
{
getFieldListString() + ', BindingObject__r.QualifiedApiName',
getFieldListString()
+ ', BindingObject__r.QualifiedApiName'
+ ', ApplicationPackage__r.DeveloperName',
getSObjectType().getDescribe().getName()
}
)
@@ -30,6 +30,8 @@
*/
public abstract class fflib_DynamicAppFactory
{
protected String packageName;
protected fflib_SharingMode sharingMode
{
get
@@ -33,9 +33,8 @@ public virtual class fflib_DynamicDomainFactory
extends fflib_DynamicAppFactory
implements fflib_IDomainFactory
{
protected Map<Object, fflib_IDomain> mockDomainByObjectType = new Map<Object, fflib_IDomain>();
protected fflib_ISelectorFactory selectorFactory;
protected fflib_ClassicDomainFactory domainFactory;
/**
* Class constructor
@@ -44,9 +43,25 @@ public virtual class fflib_DynamicDomainFactory
* @param selectorFactory A reference to the selector factory instance
*/
public fflib_DynamicDomainFactory(fflib_IAppBindingResolver resolver, fflib_ISelectorFactory selectorFactory)
{
this(resolver, selectorFactory, null);
}
/**
* Class constructor
*
* @param resolver A reference to the resolve instance
* @param selectorFactory A reference to the selector factory instance
* @param packageName The package name
*/
public fflib_DynamicDomainFactory(
fflib_IAppBindingResolver resolver,
fflib_ISelectorFactory selectorFactory,
String packageName)
{
this.resolver = resolver;
this.selectorFactory = selectorFactory;
this.packageName = packageName;
}
public fflib_IDomain newInstance(Set<Id> recordIds)
@@ -61,42 +76,16 @@ public virtual class fflib_DynamicDomainFactory
public fflib_IDomain newInstance(List<SObject> records)
{
SObjectType sObjectType = records.getSObjectType();
if (domainFactory == null) loadBindings();
if (sObjectType == null)
throw new DeveloperException('Could not determine the SObjectType of the provided records');
return newInstance(
(List<Object>) records,
(Object) sObjectType
);
return this.domainFactory.newInstance(records);
}
public fflib_IDomain newInstance(List<Object> objects, Object objectType)
{
if (hasMock(objectType)) return (fflib_IDomain) getMock(objectType);
if (domainFactory == null) loadBindings();
List<fflib_IAppBinding> bindings = resolver.byObject(objectType)
.byType(fflib_AppBindingType.Domain)
.resolve();
if (bindings.isEmpty())
throw new DeveloperException('Unable to find domain binding for ' + objectType);
System.Type domainImplementationType = bindings.get(0).getImplementationType();
Object instance = domainImplementationType.newInstance();
if (!(instance instanceof fflib_IDomainConstructor))
throw new DeveloperException(
String.format(
'Domain implementation {0} should be an instance of fflib_IDomainConstructor',
new List<String> { domainImplementationType.getName() }
)
);
return ((fflib_IDomainConstructor) domainImplementationType.newInstance())
.construct(objects);
return this.domainFactory.newInstance(objects, objectType);
}
public fflib_IDomain newInstance(List<SObject> records, SObjectType domainSObjectType)
@@ -106,22 +95,47 @@ public virtual class fflib_DynamicDomainFactory
public void setMock(fflib_ISObjectDomain mockDomain)
{
super.setMock(mockDomain.getType(), mockDomain);
if (domainFactory == null) loadBindings();
this.domainFactory.setMock(mockDomain);
}
public void setMock(Schema.SObjectType sObjectType, fflib_ISObjectDomain mockDomain)
{
super.setMock(sObjectType, mockDomain);
if (domainFactory == null) loadBindings();
this.domainFactory.setMock(sObjectType, mockDomain);
}
public void setMock(fflib_IDomain mockDomain)
{
super.setMock(mockDomain.getType(), mockDomain);
if (domainFactory == null) loadBindings();
this.domainFactory.setMock(mockDomain);
}
public void setMock(Object domainType, fflib_IDomain mockDomain)
{
super.setMock(domainType, mockDomain);
if (domainFactory == null) loadBindings();
this.domainFactory.setMock(domainType, mockDomain);
}
private void loadBindings()
{
fflib_IAppBindings appBindings = new fflib_AppBindings(resolver.resolve());
// If a package name is provide we should filter on package name
if (String.isNotBlank(this.packageName))
{
appBindings = appBindings.selectByPackageName(this.packageName);
}
Map<Object, Type> constructorByObject =
appBindings.selectByType(fflib_AppBindingType.Domain)
.getImplementationByBindingObject();
this.domainFactory = new fflib_ClassicDomainFactory(this.selectorFactory, constructorByObject);
}
public class DeveloperException extends Exception {}
@@ -32,86 +32,66 @@ public virtual class fflib_DynamicSelectorFactory
extends fflib_DynamicAppFactory
implements fflib_ISelectorFactory
{
public static final fflib_AppBindingType SELECTOR_BINDING_TYPE = fflib_AppBindingType.Selector;
protected Map<Object, Object> mockSelectorImplByObjectType = new Map<Object, Object>();
protected fflib_ClassicSelectorFactory selectorFactory;
public fflib_DynamicSelectorFactory(fflib_IAppBindingResolver resolver)
{
this(resolver, null);
}
public fflib_DynamicSelectorFactory(fflib_IAppBindingResolver resolver, String packageName)
{
this.resolver = resolver;
this.packageName = packageName;
}
public fflib_ISObjectSelector newInstance(SObjectType sObjectType)
{
if (hasMock(sObjectType)) return (fflib_ISObjectSelector) getMock(sObjectType);
if (this.selectorFactory == null) loadBindings();
List<fflib_IAppBinding> bindings = resolver
.byType(SELECTOR_BINDING_TYPE)
.byObject(sObjectType)
.bySharingMode(sharingMode)
.resolve();
if (bindings.isEmpty())
throw new DeveloperException(
String.format(
'Unable to find selector binding for {0} with sharing mode {1}',
new List<String>
{
sObjectType.getDescribe().getName(),
sharingMode.name()
}
)
);
return (fflib_ISObjectSelector) bindings.get(0).newImplInstance();
return this.selectorFactory.newInstance(sObjectType);
}
public List<SObject> selectById(Set<Id> recordIds)
{
if (null == recordIds || recordIds.size() == 0)
throw new fflib_Application.DeveloperException('Invalid record Id\'s set');
if (this.selectorFactory == null) loadBindings();
return selectById(recordIds, new List<Id>(recordIds)[0].getSObjectType());
return this.selectorFactory.selectById(recordIds);
}
public List<SObject> selectById(Set<Id> recordIds, SObjectType sObjectType)
{
if (null == recordIds || recordIds.size() == 0)
throw new fflib_Application.DeveloperException('Invalid record Id\'s set');
if (this.selectorFactory == null) loadBindings();
return newInstance(sObjectType)
.selectSObjectsById(recordIds);
return this.selectorFactory.selectById(recordIds, sObjectType);
}
public List<SObject> selectByRelationship(List<SObject> relatedRecords, SObjectField relationshipField)
{
Set<Id> relatedIds =
new RelatedRecordsDomain(relatedRecords)
.getRelatedIds(relationshipField);
if (this.selectorFactory == null) loadBindings();
if (relatedIds.isEmpty()) return new List<SObject>();
return selectById(relatedIds);
return this.selectorFactory.selectByRelationship(relatedRecords, relationshipField);
}
public void replaceWith(SObjectType sObjectType, Type replacementImplType)
{
resolver.byType(fflib_AppBindingType.Selector)
.byObject(sObjectType)
.bySharingMode(this.sharingMode)
.resolve()
.get(0)
.setImplementationType(replacementImplType);
if (this.selectorFactory == null) loadBindings();
this.selectorFactory.replaceWith(sObjectType, replacementImplType);
}
public void setMock(fflib_ISObjectSelector selectorInstance)
{
setMock(selectorInstance.sObjectType(), selectorInstance);
if (this.selectorFactory == null) loadBindings();
this.selectorFactory.setMock(selectorInstance);
}
public void setMock(SObjectType sObjectType, fflib_ISObjectSelector selectorInstance)
{
super.setMock(sObjectType, selectorInstance);
if (this.selectorFactory == null) loadBindings();
this.selectorFactory.setMock(sObjectType, selectorInstance);
}
public fflib_DynamicSelectorFactory setSharingMode(fflib_SharingMode sharingMode)
@@ -120,17 +100,22 @@ public virtual class fflib_DynamicSelectorFactory
return this;
}
private class RelatedRecordsDomain extends fflib_SObjects2
private void loadBindings()
{
public RelatedRecordsDomain(List<SObject> records)
fflib_IAppBindings appBindings = new fflib_AppBindings(resolver.resolve());
// If a package name is provide we should filter on package name
if (String.isNotBlank(this.packageName))
{
super(records);
appBindings = appBindings.selectByPackageName(this.packageName);
}
public Set<Id> getRelatedIds(Schema.SObjectField relationshipField)
{
return getIdFieldValues(relationshipField);
}
Map<SObjectType, Type> implementationBySObjectType =
appBindings.selectByType(fflib_AppBindingType.Selector)
.selectBySharingMode(this.sharingMode)
.getImplementationBySObjectType();
this.selectorFactory = new fflib_ClassicSelectorFactory(implementationBySObjectType);
}
public class DeveloperException extends Exception {}
@@ -32,53 +32,38 @@ public virtual class fflib_DynamicServiceFactory
extends fflib_DynamicAppFactory
implements fflib_IServiceFactory
{
public static final fflib_AppBindingType SERVICE_BINDING_TYPE = fflib_AppBindingType.Service;
protected Map<System.Type, Object> mockServiceImplByObjectType = new Map<System.Type, Object>();
protected fflib_ClassicServiceFactory serviceFactory;
public fflib_DynamicServiceFactory(fflib_IAppBindingResolver resolver)
{
this(resolver, null);
}
public fflib_DynamicServiceFactory(fflib_IAppBindingResolver resolver, String packageName)
{
this.resolver = resolver;
this.packageName = packageName;
}
public Object newInstance(Type serviceInterfaceType)
{
if (hasMock(serviceInterfaceType)) return getMock(serviceInterfaceType);
if (serviceFactory == null) loadBindings();
List<fflib_IAppBinding> bindings = resolver
.byType(SERVICE_BINDING_TYPE)
.byInterfaceType(serviceInterfaceType)
.bySharingMode(sharingMode)
.resolve();
if (bindings.isEmpty())
throw new DeveloperException(
String.format(
'Unable to find service binding for {0} with sharing more {1}',
new List<String>
{
serviceInterfaceType.getName(),
sharingMode.name()
}
)
);
return bindings.get(0).newImplInstance();
return this.serviceFactory.newInstance(serviceInterfaceType);
}
public void replaceWith(Type serviceInterfaceType, Type replacementImplType)
{
resolver.byType(SERVICE_BINDING_TYPE)
.byInterfaceType(serviceInterfaceType)
.bySharingMode(sharingMode)
.resolve()
.get(0) // TODO - validate that there are any resolved bindings
.setImplementationType(replacementImplType);
if (serviceFactory == null) loadBindings();
this.serviceFactory.replaceWith(serviceInterfaceType, replacementImplType);
}
public void setMock(Type serviceInterfaceType, Object serviceImpl)
{
super.setMock(serviceInterfaceType, serviceImpl);
if (serviceFactory == null) loadBindings();
this.serviceFactory.setMock(serviceInterfaceType, serviceImpl);
}
public fflib_DynamicServiceFactory setSharingMode(fflib_SharingMode sharingMode)
@@ -87,5 +72,22 @@ public virtual class fflib_DynamicServiceFactory
return this;
}
private void loadBindings()
{
fflib_IAppBindings appBindings = new fflib_AppBindings(resolver.resolve());
// If a package name is provide we should filter on package name
if (String.isNotBlank(this.packageName))
{
appBindings = appBindings.selectByPackageName(this.packageName);
}
Map<Type, Type> implementationByInterface =
appBindings.selectByType(fflib_AppBindingType.Service)
.getImplementationByInterface();
this.serviceFactory = new fflib_ClassicServiceFactory(implementationByInterface);
}
public class DeveloperException extends Exception {}
}
@@ -56,6 +56,10 @@ public interface fflib_IAppBinding
* @return Returns the Namespace for the binding
*/
String getNamespacePrefix();
/**
* @return Returns the Application Package Name for the binding
*/
String getPackageName();
/**
* @return Returns the number of the order sequence in which the binding should be returned
@@ -127,6 +131,13 @@ public interface fflib_IAppBinding
*/
fflib_IAppBinding setNamespacePrefix(String namespacePrefix);
/**
* @param applicationPackageName The name of the Application Second Generation Package
*
* @return An instance of itself to enable method chaining
*/
fflib_IAppBinding setPackageName(String applicationPackageName);
/**
* Set the order number so that the resolver can sort the bindings.
* The higher the number, the more priority.
@@ -37,5 +37,6 @@ public interface fflib_IAppBindingResolver
fflib_IAppBindingResolver byInterfaceType(System.Type interfaceType);
fflib_IAppBindingResolver bySharingMode(fflib_SharingMode sharingMode);
fflib_IAppBindingResolver byNamespacePrefix(String namespacePrefix);
fflib_IAppBindingResolver byPackageName(String packageName);
List<fflib_IAppBinding> resolve();
}
@@ -34,13 +34,17 @@ public interface fflib_IAppBindings
void addBinding(fflib_IAppBinding binding);
void addBindings(List<fflib_IAppBinding> bindings);
List<fflib_IAppBinding> getBindings();
Map<Object, Type> getImplementationByBindingObject();
Map<Type, Type> getImplementationByInterface();
Map<SObjectType, Type> getImplementationBySObjectType();
List<System.Type> getImplementations();
fflib_IAppBindings selectByObject(Object bindingObject);
fflib_IAppBindings selectBySequence(Decimal sequence);
fflib_IAppBindings selectByType(fflib_AppBindingType bindingType);
fflib_IAppBindings selectByInterfaceType(System.Type interfaceType);
fflib_IAppBindings selectBySharingMode(fflib_SharingMode sharingMode);
fflib_IAppBindings selectByNamespacePrefix(String namespacePrefix);
List<fflib_IAppBinding> getBindings();
List<System.Type> getImplementations();
fflib_IAppBindings selectByPackageName(String packageName);
}
@@ -18,6 +18,10 @@
<behavior>Required</behavior>
<field>Type__c</field>
</layoutItems>
<layoutItems>
<behavior>Edit</behavior>
<field>ApplicationPackage__c</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Layout xmlns="http://soap.sforce.com/2006/04/metadata">
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>false</detailHeading>
<editHeading>true</editHeading>
<label>Information</label>
<layoutColumns>
<layoutItems>
<behavior>Required</behavior>
<field>MasterLabel</field>
</layoutItems>
<layoutItems>
<behavior>Required</behavior>
<field>DeveloperName</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Edit</behavior>
<field>IsProtected</field>
</layoutItems>
<layoutItems>
<behavior>Required</behavior>
<field>NamespacePrefix</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>false</detailHeading>
<editHeading>true</editHeading>
<label>System Information</label>
<layoutColumns>
<layoutItems>
<behavior>Readonly</behavior>
<field>CreatedById</field>
</layoutItems>
</layoutColumns>
<layoutColumns>
<layoutItems>
<behavior>Readonly</behavior>
<field>LastModifiedById</field>
</layoutItems>
</layoutColumns>
<style>TwoColumnsTopToBottom</style>
</layoutSections>
<layoutSections>
<customLabel>false</customLabel>
<detailHeading>false</detailHeading>
<editHeading>false</editHeading>
<layoutColumns/>
<style>CustomLinks</style>
</layoutSections>
<relatedLists>
<fields>MasterLabel</fields>
<fields>DeveloperName</fields>
<fields>NamespacePrefix</fields>
<relatedList>fflib_AppBinding__mdt.ApplicationPackage__c</relatedList>
</relatedLists>
<showEmailCheckbox>false</showEmailCheckbox>
<showHighlightsPanel>false</showHighlightsPanel>
<showInteractionLogPanel>false</showInteractionLogPanel>
<showRunAssignmentRulesCheckbox>false</showRunAssignmentRulesCheckbox>
<showSubmitAndAttachButton>false</showSubmitAndAttachButton>
</Layout>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>ApplicationPackage__c</fullName>
<externalId>false</externalId>
<fieldManageability>DeveloperControlled</fieldManageability>
<label>Application Package</label>
<referenceTo>fflib_ApplicationPackage__mdt</referenceTo>
<relationshipLabel>Application Bindings</relationshipLabel>
<relationshipName>ApplicationBindings</relationshipName>
<required>false</required>
<type>MetadataRelationship</type>
<unique>false</unique>
</CustomField>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Define individual packages if your application contains multiple second generation packages (2GP)</description>
<label>Application Package</label>
<pluralLabel>Application Packages</pluralLabel>
<visibility>Public</visibility>
</CustomObject>
@@ -111,6 +111,5 @@ public with sharing class fflib_MockSObjectUtil
Lead record = new Lead(Id = fflib_IDGenerator.generate(Schema.Lead.SObjectType));
SObject result = addFieldValue(record, Lead.ConvertedDate, today);
System.assertEquals(today, result.get(Lead.ConvertedDate));
System.debug('result: '+result);
}
}
@@ -31,15 +31,24 @@
@IsTest(IsParallel=true)
public class fflib_DynamicDomainFactoryTest
{
private static final SObjectType ACCOUNT_OBJECT_TYPE = Schema.Account.SObjectType;
private static final String PACKAGE_FORCE_APP = 'force-app';
private static final String PACKAGE_OTHER_APP = 'other-app';
private static final fflib_IAppBindingResolver bindingResolver =
new fflib_AppBindingResolver();
private static final fflib_DynamicDomainFactory Domain =
new fflib_DynamicDomainFactory(
bindingResolver,
fflib_DynamicSelectorFactoryTest.Selector);
private static final SObjectType ACCOUNT_OBJECT_TYPE = Schema.Account.SObjectType;
fflib_DynamicSelectorFactoryTest.Selector,
PACKAGE_FORCE_APP);
private static final fflib_DynamicDomainFactory OtherDomain =
new fflib_DynamicDomainFactory(
bindingResolver,
fflib_DynamicSelectorFactoryTest.Selector,
PACKAGE_OTHER_APP);
@IsTest
static void itShouldReturnDomain()
@@ -107,6 +116,19 @@ public class fflib_DynamicDomainFactoryTest
System.Assert.isTrue(instanceB.getRecords().isEmpty());
}
@IsTest
static void itShouldReturnTheRightDomainForThePackage()
{
fflib_AppBindingsSelector.SELECTOR_IMPL_TYPE = AppBindingsSelectorMock.class;
final List<Account> records = generateAccountRecords();
System.Test.startTest();
fflib_IDomain otherDomain = OtherDomain.newInstance(records);
System.Test.stopTest();
System.Assert.isTrue(otherDomain instanceof fflib_SObjects2, 'Incorrect returned instance');
}
private static List<Account> generateAccountRecords()
{
@@ -128,18 +150,46 @@ public class fflib_DynamicDomainFactoryTest
}
}
public class OtherDomainConstructor implements fflib_IDomainConstructor
{
public fflib_IDomain construct(List<Object> objects)
{
return new fflib_SObjects2((List<SObject>) objects);
}
}
private class AppBindingsSelectorMock extends fflib_AppBindingsSelector
{
public override List<fflib_AppBinding__mdt> selectAll()
{
fflib_ApplicationPackage__mdt forceApp =
new fflib_ApplicationPackage__mdt(
Id = fflib_IDGenerator.generate(fflib_ApplicationPackage__mdt.SObjectType),
DeveloperName = PACKAGE_FORCE_APP);
fflib_ApplicationPackage__mdt otherApp =
new fflib_ApplicationPackage__mdt(
Id = fflib_IDGenerator.generate(fflib_ApplicationPackage__mdt.SObjectType),
DeveloperName = PACKAGE_OTHER_APP);
return new List<fflib_AppBinding__mdt>
{
new fflib_AppBinding__mdt(
ApplicationPackage__c = forceApp.Id,
ApplicationPackage__r = forceApp,
Type__c = 'Domain',
BindingObject__c = '',
BindingObjectAlternate__c = ACCOUNT_OBJECT_TYPE.getDescribe().getName(),
ImplementationType__c = MyDomainConstructor.class.getName(),
SharingMode__c = 'None'
),
new fflib_AppBinding__mdt(
ApplicationPackage__c = otherApp.Id,
ApplicationPackage__r = otherApp,
Type__c = 'Domain',
BindingObject__c = '',
BindingObjectAlternate__c = ACCOUNT_OBJECT_TYPE.getDescribe().getName(),
ImplementationType__c = OtherDomainConstructor.class.getName(),
SharingMode__c = 'None'
)
};
}
@@ -153,7 +153,6 @@ private class fflib_SObjects2Test
}
);
System.Test.stopTest();
System.debug('result: ' + JSON.serializePretty(result));
// THEN it should return the AccountId By CaseId
System.Assert.areEqual(1, result.size(), 'Expected one account');
@@ -194,7 +193,6 @@ private class fflib_SObjects2Test
}
);
System.Test.stopTest();
System.debug('result: ' + JSON.serializePretty(result));
// THEN it should return the AccountId By CaseId
System.Assert.areEqual(1, result.size(), 'Expected one account');
@@ -91,7 +91,6 @@ private class fflib_LogEventAppenderTest
fflib_LogEventAppender eventAppender = new fflib_LogEventAppender();
fflib_LogLevelFilter__c orgSettings = fflib_LogLevelFilter__c.getOrgDefaults();
System.debug(orgSettings);
orgSettings.LogLevel__c = 'INFO';
insert orgSettings;
@@ -96,7 +96,6 @@ private class fflib_LoggerTest
// THEN - It should be appended to the logAppender
final List<String> result = APPENDER_MOCK
.getAppendedMessages(System.LoggingLevel.DEBUG);
System.debug(result);
System.Assert.areEqual(1, result.size(), 'Expected only one error');
System.Assert.isTrue(result.get(0).startsWith(ERROR_MESSAGE_FORMATTED_WITH_EXCEPTION), 'Incorrect returned error message');
}