@@ -112,6 +112,9 @@ public virtual class fflib_Application
112112 return new fflib_SObjectUnitOfWork (objectTypes , dml );
113113 }
114114
115+ /**
116+ * @param mockUow A mock implementation for the unitOfWork factory
117+ */
115118 @TestVisible
116119 protected virtual void setMock (fflib_ISObjectUnitOfWork mockUow )
117120 {
@@ -168,6 +171,24 @@ public virtual class fflib_Application
168171 return serviceImpl .newInstance ();
169172 }
170173
174+ /**
175+ * Creates or replaces an existing binding for another
176+ *
177+ * @param serviceInterfaceType The Interface type to replace its implementation
178+ * @param replacementImplType The implementation type of the replacement
179+ */
180+ public virtual void replaceWith (Type serviceInterfaceType , Type replacementImplType )
181+ {
182+ this .m_serviceInterfaceTypeByServiceImplType .put (
183+ serviceInterfaceType ,
184+ replacementImplType
185+ );
186+ }
187+
188+ /**
189+ * @param serviceInterfaceType The interface type to mock
190+ * @param serviceImpl The mock implementation
191+ */
171192 @TestVisible
172193 protected virtual void setMock (Type serviceInterfaceType , Object serviceImpl )
173194 {
@@ -246,6 +267,27 @@ public virtual class fflib_Application
246267 return newInstance (domainSObjectType ).selectSObjectsById (recordIds );
247268 }
248269
270+ /**
271+ * Helper method to query the given SObject records
272+ * Internally creates an instance of the registered Selector and calls its
273+ * selectSObjectById method.
274+ * It assumes that all Ids are of the given SObjectType, no additional validation is done.
275+ *
276+ * @param recordIds The recordIds to query
277+ * @param sObjectType The SObjectType of the Ids
278+ *
279+ * @return The queried records
280+ * @exception fflib_Application.DeveloperException is thrown if the Ids set is empty
281+ */
282+ public virtual List <SObject > selectById (Set <Id > recordIds , SObjectType sObjectType )
283+ {
284+ if (recordIds == null || recordIds .size () == 0 )
285+ throw new fflib_Application .DeveloperException (' Invalid record Id\' s set' );
286+
287+ return newInstance (sObjectType )
288+ .selectSObjectsById (recordIds );
289+ }
290+
249291 /**
250292 * Helper method to query related records to those provided, for example
251293 * if passed a list of Opportunity records and the Account Id field will
@@ -270,19 +312,44 @@ public virtual class fflib_Application
270312 return selectById (relatedIds );
271313 }
272314
315+ /**
316+ * Creates or replaces an existing binding for another
317+ *
318+ * @param sObjectType The SObjectType of the selector to replace
319+ * @param replacementImplType The implementation type of the replacement
320+ */
321+ public virtual void replaceWith (SObjectType sObjectType , Type replacementImplType )
322+ {
323+ this .m_sObjectBySelectorType .put (sObjectType , replacementImplType );
324+ }
325+
326+ /**
327+ * @param selectorInstance The instance of the mocked selector
328+ */
273329 @TestVisible
274330 protected virtual void setMock (fflib_ISObjectSelector selectorInstance )
275331 {
276332 m_sObjectByMockSelector .put (selectorInstance .sObjectType (), selectorInstance );
277- }
333+ }
334+
335+ /**
336+ * @param sObjectType The SObjectType of the selector mock,
337+ * avoids the need to stub the mock to return its SObjectType
338+ * @param selectorInstance The instance of the mocked selector
339+ */
340+ @TestVisible
341+ protected virtual void setMock (SObjectType sObjectType , fflib_ISObjectSelector selectorInstance )
342+ {
343+ this .m_sObjectByMockSelector .put (sObjectType , selectorInstance );
344+ }
278345 }
279346
280347 /**
281348 * Class implements a Domain class factory
282349 **/
283350 public virtual class DomainFactory implements fflib_IDomainFactory
284351 {
285- protected fflib_Application. SelectorFactory m_selectorFactory ;
352+ protected fflib_ISelectorFactory m_selectorFactory ;
286353
287354 protected Map <Object , Type > constructorTypeByObject ;
288355
@@ -302,10 +369,10 @@ public virtual class fflib_Application
302369 * @param selectorFactory , e.g. Application.Selector
303370 * @param constructorTypeByObject Map of Domain classes by ObjectType
304371 **/
305- public DomainFactory (fflib_Application. SelectorFactory selectorFactory ,
372+ public DomainFactory (fflib_ISelectorFactory selectorFactory ,
306373 Map <Object , Type > constructorTypeByObject )
307374 {
308- m_selectorFactory = selectorFactory ;
375+ this . m_selectorFactory = selectorFactory ;
309376 this .constructorTypeByObject = constructorTypeByObject ;
310377 this .mockDomainByObject = new Map <Object , fflib_IDomain >();
311378 }
@@ -319,10 +386,10 @@ public virtual class fflib_Application
319386 * @param selectorFactory, e.g. Application.Selector
320387 * @param sObjectByDomainConstructorType Map of Apex classes by SObjectType
321388 **/
322- public DomainFactory (fflib_Application. SelectorFactory selectorFactory ,
389+ public DomainFactory (fflib_ISelectorFactory selectorFactory ,
323390 Map <SObjectType , Type > sObjectByDomainConstructorType )
324391 {
325- m_selectorFactory = selectorFactory ;
392+ this . m_selectorFactory = selectorFactory ;
326393 this .constructorTypeByObject = getConstructorTypeByObject (sObjectByDomainConstructorType );
327394 this .mockDomainByObject = new Map <Object , fflib_IDomain >();
328395 }
@@ -338,7 +405,22 @@ public virtual class fflib_Application
338405 public virtual fflib_IDomain newInstance (Set <Id > recordIds )
339406 {
340407 return newInstance (m_selectorFactory .selectById (recordIds ));
408+ }
341409
410+ /**
411+ * Dynamically constructs an instance of a Domain class for the given record Ids
412+ * Internally uses the Selector Factory to query the records before passing to a
413+ * dynamically constructed instance of the application Apex Domain class
414+ *
415+ * @param recordIds A list of Id's of the same type
416+ * @param sObjectType The SObjectType of the given record Ids
417+ *
418+ * @return Instance of a Domain containing the queried records
419+ * @exception Throws an exception via the Selector Factory if the Ids are not all of the same SObjectType
420+ **/
421+ public virtual fflib_IDomain newInstance (Set <Id > recordIds , Schema.SObjectType sObjectType )
422+ {
423+ return newInstance (m_selectorFactory .selectById (recordIds , sObjectType ), sObjectType );
342424 }
343425
344426 /**
@@ -412,18 +494,60 @@ public virtual class fflib_Application
412494 );
413495 }
414496
497+ /**
498+ * Creates or replaces an existing binding for another
499+ *
500+ * @param sObjectType The SObjectType of the selector to replace
501+ * @param replacementImplType The implementation type of the replacement
502+ */
503+ public virtual void replaceWith (Schema.SObjectType sObjectType , Type replacementImplType )
504+ {
505+ this .constructorTypeByObject .put (
506+ (Object ) sObjectType ,
507+ replacementImplType
508+ );
509+ }
510+
511+ /**
512+ * @param mockDomain The instance of the Domain mock
513+ */
415514 @TestVisible
416515 protected virtual void setMock (fflib_ISObjectDomain mockDomain )
417516 {
418517 mockDomainByObject .put ((Object ) mockDomain .sObjectType (), (fflib_IDomain ) mockDomain );
419518 }
420519
520+ /**
521+ * @param mockDomain The instance of the Domain mock
522+ */
421523 @TestVisible
422524 protected virtual void setMock (fflib_IDomain mockDomain )
423525 {
424526 mockDomainByObject .put (mockDomain .getType (), mockDomain );
425527 }
426528
529+ /**
530+ * @param sObjectType The SObjectType of the Domain mock,
531+ * avoids the need to stub the mock to return its SObjectType
532+ * @param mockDomain The instance of the Domain mock
533+ */
534+ @TestVisible
535+ protected virtual void setMock (Schema.SObjectType sObjectType , fflib_ISObjectDomain mockDomain )
536+ {
537+ mockDomainByObject .put ((Object ) sObjectType , mockDomain );
538+ }
539+
540+ /**
541+ * @param domainType The ObjectType of the Domain mock,
542+ * avoids the need to stub the mock to return its ObjectType
543+ * @param mockDomain The instance of the Domain mock
544+ */
545+ @TestVisible
546+ protected virtual void setMock (Object domainType , fflib_IDomain mockDomain )
547+ {
548+ mockDomainByObject .put (domainType , mockDomain );
549+ }
550+
427551 protected virtual Map <Object , Type > getConstructorTypeByObject (Map <SObjectType , Type > constructorTypeBySObjectType )
428552 {
429553 Map <Object , Type > result = new Map <Object , Type >();
0 commit comments