@@ -112,8 +112,10 @@ public virtual class fflib_Application
112112 return new fflib_SObjectUnitOfWork (objectTypes , dml );
113113 }
114114
115- @TestVisible
116- protected virtual void setMock (fflib_ISObjectUnitOfWork mockUow )
115+ /**
116+ * @param mockUow A mock implementation for the unitOfWork factory
117+ */
118+ public virtual void setMock (fflib_ISObjectUnitOfWork mockUow )
117119 {
118120 m_mockUow = mockUow ;
119121 }
@@ -168,8 +170,25 @@ public virtual class fflib_Application
168170 return serviceImpl .newInstance ();
169171 }
170172
171- @TestVisible
172- protected virtual void setMock (Type serviceInterfaceType , Object serviceImpl )
173+ /**
174+ * Creates or replaces an existing binding for another
175+ *
176+ * @param serviceInterfaceType The Interface type to replace its implementation
177+ * @param replacementImplType The implementation type of the replacement
178+ */
179+ public virtual void replaceWith (Type serviceInterfaceType , Type replacementImplType )
180+ {
181+ this .m_serviceInterfaceTypeByServiceImplType .put (
182+ serviceInterfaceType ,
183+ replacementImplType
184+ );
185+ }
186+
187+ /**
188+ * @param serviceInterfaceType The interface type to mock
189+ * @param serviceImpl The mock implementation
190+ */
191+ public virtual void setMock (Type serviceInterfaceType , Object serviceImpl )
173192 {
174193 m_serviceInterfaceTypeByMockService .put (serviceInterfaceType , serviceImpl );
175194 }
@@ -246,6 +265,27 @@ public virtual class fflib_Application
246265 return newInstance (domainSObjectType ).selectSObjectsById (recordIds );
247266 }
248267
268+ /**
269+ * Helper method to query the given SObject records
270+ * Internally creates an instance of the registered Selector and calls its
271+ * selectSObjectById method.
272+ * It assumes that all Ids are of the given SObjectType, no additional validation is done.
273+ *
274+ * @param recordIds The recordIds to query
275+ * @param sObjectType The SObjectType of the Ids
276+ *
277+ * @return The queried records
278+ * @exception fflib_Application.DeveloperException is thrown if the Ids set is empty
279+ */
280+ public virtual List <SObject > selectById (Set <Id > recordIds , SObjectType sObjectType )
281+ {
282+ if (recordIds == null || recordIds .size () == 0 )
283+ throw new fflib_Application .DeveloperException (' Invalid record Id\' s set' );
284+
285+ return newInstance (sObjectType )
286+ .selectSObjectsById (recordIds );
287+ }
288+
249289 /**
250290 * Helper method to query related records to those provided, for example
251291 * if passed a list of Opportunity records and the Account Id field will
@@ -270,19 +310,42 @@ public virtual class fflib_Application
270310 return selectById (relatedIds );
271311 }
272312
273- @TestVisible
274- protected virtual void setMock (fflib_ISObjectSelector selectorInstance )
313+ /**
314+ * Creates or replaces an existing binding for another
315+ *
316+ * @param sObjectType The SObjectType of the selector to replace
317+ * @param replacementImplType The implementation type of the replacement
318+ */
319+ public virtual void replaceWith (SObjectType sObjectType , Type replacementImplType )
320+ {
321+ this .m_sObjectBySelectorType .put (sObjectType , replacementImplType );
322+ }
323+
324+ /**
325+ * @param selectorInstance The instance of the mocked selector
326+ */
327+ public virtual void setMock (fflib_ISObjectSelector selectorInstance )
275328 {
276329 m_sObjectByMockSelector .put (selectorInstance .sObjectType (), selectorInstance );
277- }
330+ }
331+
332+ /**
333+ * @param sObjectType The SObjectType of the selector mock,
334+ * avoids the need to stub the mock to return its SObjectType
335+ * @param selectorInstance The instance of the mocked selector
336+ */
337+ public virtual void setMock (SObjectType sObjectType , fflib_ISObjectSelector selectorInstance )
338+ {
339+ this .m_sObjectByMockSelector .put (sObjectType , selectorInstance );
340+ }
278341 }
279342
280343 /**
281344 * Class implements a Domain class factory
282345 **/
283346 public virtual class DomainFactory implements fflib_IDomainFactory
284347 {
285- protected fflib_Application. SelectorFactory m_selectorFactory ;
348+ protected fflib_ISelectorFactory m_selectorFactory ;
286349
287350 protected Map <Object , Type > constructorTypeByObject ;
288351
@@ -302,10 +365,10 @@ public virtual class fflib_Application
302365 * @param selectorFactory , e.g. Application.Selector
303366 * @param constructorTypeByObject Map of Domain classes by ObjectType
304367 **/
305- public DomainFactory (fflib_Application. SelectorFactory selectorFactory ,
368+ public DomainFactory (fflib_ISelectorFactory selectorFactory ,
306369 Map <Object , Type > constructorTypeByObject )
307370 {
308- m_selectorFactory = selectorFactory ;
371+ this . m_selectorFactory = selectorFactory ;
309372 this .constructorTypeByObject = constructorTypeByObject ;
310373 this .mockDomainByObject = new Map <Object , fflib_IDomain >();
311374 }
@@ -319,10 +382,10 @@ public virtual class fflib_Application
319382 * @param selectorFactory, e.g. Application.Selector
320383 * @param sObjectByDomainConstructorType Map of Apex classes by SObjectType
321384 **/
322- public DomainFactory (fflib_Application. SelectorFactory selectorFactory ,
385+ public DomainFactory (fflib_ISelectorFactory selectorFactory ,
323386 Map <SObjectType , Type > sObjectByDomainConstructorType )
324387 {
325- m_selectorFactory = selectorFactory ;
388+ this . m_selectorFactory = selectorFactory ;
326389 this .constructorTypeByObject = getConstructorTypeByObject (sObjectByDomainConstructorType );
327390 this .mockDomainByObject = new Map <Object , fflib_IDomain >();
328391 }
@@ -338,7 +401,22 @@ public virtual class fflib_Application
338401 public virtual fflib_IDomain newInstance (Set <Id > recordIds )
339402 {
340403 return newInstance (m_selectorFactory .selectById (recordIds ));
404+ }
341405
406+ /**
407+ * Dynamically constructs an instance of a Domain class for the given record Ids
408+ * Internally uses the Selector Factory to query the records before passing to a
409+ * dynamically constructed instance of the application Apex Domain class
410+ *
411+ * @param recordIds A list of Id's of the same type
412+ * @param sObjectType The SObjectType of the given record Ids
413+ *
414+ * @return Instance of a Domain containing the queried records
415+ * @exception Throws an exception via the Selector Factory if the Ids are not all of the same SObjectType
416+ **/
417+ public virtual fflib_IDomain newInstance (Set <Id > recordIds , Schema.SObjectType sObjectType )
418+ {
419+ return newInstance (m_selectorFactory .selectById (recordIds , sObjectType ), sObjectType );
342420 }
343421
344422 /**
@@ -412,18 +490,56 @@ public virtual class fflib_Application
412490 );
413491 }
414492
415- @TestVisible
416- protected virtual void setMock (fflib_ISObjectDomain mockDomain )
493+ /**
494+ * Creates or replaces an existing binding for another
495+ *
496+ * @param sObjectType The SObjectType of the selector to replace
497+ * @param replacementImplType The implementation type of the replacement
498+ */
499+ public virtual void replaceWith (Schema.SObjectType sObjectType , Type replacementImplType )
500+ {
501+ this .constructorTypeByObject .put (
502+ (Object ) sObjectType ,
503+ replacementImplType
504+ );
505+ }
506+
507+ /**
508+ * @param mockDomain The instance of the Domain mock
509+ */
510+ public virtual void setMock (fflib_ISObjectDomain mockDomain )
417511 {
418512 mockDomainByObject .put ((Object ) mockDomain .sObjectType (), (fflib_IDomain ) mockDomain );
419513 }
420514
421- @TestVisible
422- protected virtual void setMock (fflib_IDomain mockDomain )
515+ /**
516+ * @param mockDomain The instance of the Domain mock
517+ */
518+ public virtual void setMock (fflib_IDomain mockDomain )
423519 {
424520 mockDomainByObject .put (mockDomain .getType (), mockDomain );
425521 }
426522
523+ /**
524+ * @param sObjectType The SObjectType of the Domain mock,
525+ * avoids the need to stub the mock to return its SObjectType
526+ * @param mockDomain The instance of the Domain mock
527+ */
528+ public virtual void setMock (Schema.SObjectType sObjectType , fflib_ISObjectDomain mockDomain )
529+ {
530+ mockDomainByObject .put ((Object ) sObjectType , mockDomain );
531+ }
532+
533+ /**
534+ * @param domainType The ObjectType of the Domain mock,
535+ * avoids the need to stub the mock to return its ObjectType
536+ * @param mockDomain The instance of the Domain mock
537+ */
538+ public virtual void setMock (Object domainType , fflib_IDomain mockDomain )
539+ {
540+ mockDomainByObject .put (domainType , mockDomain );
541+ }
542+
427543 protected virtual Map <Object , Type > getConstructorTypeByObject (Map <SObjectType , Type > constructorTypeBySObjectType )
428544 {
429545 Map <Object , Type > result = new Map <Object , Type >();
0 commit comments