mattaddy / SObjectFabricator

An SObject fabrication API to reduce database interactions and dependencies on triggers in Apex unit tests.
Other
89 stars 14 forks source link

Support for mocking polymorphic parents #27

Open cropredyHelix opened 1 year ago

cropredyHelix commented 1 year ago

@bobalicious The Readme doc doesn't say that polymorphic parents aren't supported so of course, I gave it a try

Schema:

Event -> EventRelation w/ polymorphic lookup via EventRelation.Relation field to Account, Contact, Lead, User

This example

(Event) new sfab_FabricatedSObject(Event.class)                             // [0] w/ accountId IsChild
                .setField(Event.Id,fflib_IDGenerator.generate(Event.SObjectType))
                .setChildren('EventRelations',new List<sfab_FabricatedSObject> {
                    new sfab_FabricatedSObject(EventRelation.class)
                        .setField(EventRelation.Id,fflib_IDGenerator.generate(EventRelation.SObjectType))
                        .setField(EventRelation.RelationId,fflib_IDGenerator.generate(Account.SObjectType))
                        .set('Relation.Type','Account')
                        .setParent('Relation',new sfab_FabricatedSObject(Account.class)
                            .setField(Account.Id,fflib_IDGenerator.generate(Account.SObjectType)))
                })
                .toSObject()

generates exception:

sfab_ObjectDescriber.ParentRelationshipObjectCannotBeAutoCreatedException: 
Cannot automatically create a Fabricated Object for the relationship EventRelation.Relation 
as it is polymorphic and so not possible to automatically ascertain which SObject to use

If I remove the .set('Relation.Type','Account')

I get this runtime error

(System Code)
Class.sfab_FabricatedSObject.toSObject: line 291, column 1
System.JSONException: Cannot deserialize instance of <unknown> from null value null or request may be missing a required field

Thoughts

Now I don't actually know if you can round trip across polymorphic relationships but it would seem doable. sfab is told the polymorphic parentType in .setParent('Relation',new sfab_FabricatedSObject(Account.class) so the error message in

sfab_ObjectDescriber.ParentRelationshipObjectCannotBeAutoCreatedException: 
Cannot automatically create a Fabricated Object for the relationship EventRelation.Relation 
as it is polymorphic and so not possible to automatically ascertain which SObject to use

seems contradictory (i.e. ...automatially ascertain which SObject to use...)

For grins, I did a REST query on a real EventRelation and got this:

/services/data/v58.0/query?q=SELECT+Id,+TYPEOF+Relation+WHEN+Contact+THEN+Name+END+FROM+EventRelation+WHERE+EventId+=+'00UHp00000eyrRsMAI'
{
  "totalSize" : 1,
  "done" : true,
  "records" : [ {
    "attributes" : {
      "type" : "EventRelation",
      "url" : "/services/data/v58.0/sobjects/EventRelation/0REHp00000WVwEpOAL"
    },
    "Id" : "0REHp00000WVwEpOAL",
    "Relation" : {
      "attributes" : {
        "type" : "Contact",
        "url" : "/services/data/v58.0/sobjects/Contact/0031Q0000277sPgQAI"
      },
      "Name" : "MyDomain Smoketest"
    }
  } ]
}

This will deserialize into an EventRelation with proper polymorphic lookup to Contact so I would imagine if you could build the above in memory and then serialize it/deserialize in the toSobject() method, it would work