Skip to content

Documentation / installation / readme points #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
cropredyHelix opened this issue Aug 18, 2017 · 5 comments
Open

Documentation / installation / readme points #2

cropredyHelix opened this issue Aug 18, 2017 · 5 comments

Comments

@cropredyHelix
Copy link

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})
@mattaddy
Copy link
Owner

Thanks for all the suggestions!

  1. I thought about this as well, and plan to rename the classes in my next commit.
  2. I can certainly update the readme to use generated ids instead of the 'Opp-1' style.
  3. Interesting! You're right in that I've typically passed SObjectTypes around rather than Types, but is there an inherent benefit here?
  4. Can you elaborate on this point more? I would love to provide more context in the readme to increase potential adoption, but want to make sure I understand first.
  5. I agree, coupling SObject fabrication with a selector layer provides excellent benefits. Are you suggesting that we update the readme to include a section on how to incorporate it with selectors?
  6. Mocking more than one level deep is definitely a big plus as well. We should definitely call this out in the readme as well.

Again, thanks for all the suggestions! Feel free to submit a pull request for any of these recommendations, otherwise I'll likely implement them very soon.

@cropredyHelix
Copy link
Author

Matt. I appreciate the response.

#3 - I like xxx.SObjectType solely for the familiarity and consistency with other code, notably fflib.

#4 - if you are unit testing a method that updates sobject xxxx, you can't fabricate that object as the code-under-test DML will fail. Similarly, if you fabricate an Account sobject and the code under test tries to insert an Opportunity or Case or Contact, the code will fail because the lookupId won't exist in the database.

The way around this is to use the fflib pattern, unit of work layer, and Apex Mocks. Andy Fawcett's second edition Force.com Enterprise Architecture has a chapter on this.

Most apex code ultimately does DML so blending (in the readme) how to execute DML on fabricated objects would be useful to the user of your lib.

#5 Yes.

Bottom line, whereas you are an advanced developer, getting tradition-bound apex devs to use your excellent lib requires a few more examples.

Once you commit a new version with prefixes, I know I'll be adding it to our org!

@mattaddy
Copy link
Owner

@cropredyHelix I merged #3 which addresses the prefix suggestion.

@cropredyHelix
Copy link
Author

cropredyHelix commented Aug 28, 2017 via email

@Mrmattmann
Copy link

We've loved using this and I agree, more than 2 levels for child relationships is amazing! We use this along with the fflib pattern and they have a class called fflib_IDGenerator that we use to generate an ID for whatever object we are fabricating. Used with the Mocking as mentioned above makes testings much faster!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants