Skip to content

Documentation / installation / readme points #2

Open
@cropredyHelix

Description

@cropredyHelix

I like where you are going here and might make a couple of suggestions

  1. You should follow the fflib class naming convention and prefix all these classes with sfab_ or somesuch so the classes don't conflict with any other classes in one's org and are easier to track for exclusion purposes in Test Suites.
  2. Instead of using examples of IDs as 'Opp-1', use your own version of fflib_IdGenerator.generate(Opportunity.SobjectType) - this way you get Ids of the proper key prefix. This becomes important when mocking polymorphic relationship fields like OwnerId, WhatId, or WhoId as the code-under-test is using the getSobjectType() method and these will break on strings such as Opp-1
  3. The second argument to the FabricatedSObject construct is of type Type, but I wonder if it would be more natural for it to be an SobjectType? I can't think of a time where I have ever written Account.class but often would use Account.SobjectType.
  4. When combined with the fflib UnitOfWork pattern and ApexMocks, your fabricated objects can even be unit tested to see if they were updated as expected (all but the DML). Adding to your ReadMe to show how this could be done would avoid the natural inclination of most developers to reject such a fabrication framework because the mocked Sobjects can't be updated and most code that gets unit tested does updates.
  5. The framework becomes even more useful when coupled with the fflib Selector layer so code-under-test can mock the results going from, say, a fabricated OpportunityLineItem to its Product2 via PricebookEntryId. That is, the mocked Selector is returning fabricated Sobjects. In our shop, real world tests involve having to mock Account + Contact + Order + OrderItem(s) + Product2(s) + PricebookEntry(s) + Pricebook2. This is not an uncommon use case.
  6. Your framework does something I at first thought was impossible, but it can mock more than one level deep! This is super useful. It needs calling out in the ReadMe. See the code below
FabricatedSObject fabricatedAccount = new FabricatedSObject(Account.class);  // mock Acct
fabricatedAccount.setField(Account.Id, 'AId-1');

FabricatedSObject fabricatedCase = new FabricatedSObject(Case.class);  // mock Case
fabricatedCase.setField(Case.Id, 'CsId-1');

FabricatedSObject fabricatedCaseComment = new FabricatedSObject(CaseComment.class);  // mock CaseComment 
fabricatedCaseComment.setField(CaseComment.Id, 'CsCId-1');

fabricatedAccount.setChildren('Cases', new List<FabricatedSObject> {fabricatedCase});
fabricatedCase.setChildren('CaseComments',new List<FabricatedSobject> {fabricatedCaseComment});

Account acct = (Account)new SObjectFabricator().fabricate(fabricatedAccount);

System.debug(LoggingLevel.INFO,'acct='+acct);
System.debug(LoggingLevel.INFO,'cases='+acct.Cases);
System.debug(LoggingLevel.INFO,'caseComment on Case[0]='+acct.Cases[0].CaseComments);

with results:

acct=Account:{Id=AId-1}
cases=(Case:{Id=CsId-1})
caseComment on Case[0]=(CaseComment:{Id=CsCId-1})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions