Dynamic casting of SObject objects?
No, there's no way to do a dynamic typecast in apex. However what you can do to work around this is make a virtual or abstract class with all of the logic using the dynamic apex form (e.g. record.put
). Then have a subclass for the Lead
type that wraps this method's return type in a Lead
cast.
For example:
public abstract class GenericFactory{
public SObject makeRecord(Map<SObjectField, Object> valuesByField) {
// Initialize the Lead object to return
SObject record = this.getSObjectType().newSObject(null, true);
// Populate the record with values passed to the method
for (SObjectField eachField : valuesByField.keySet()) {
record.put(eachField, valuesByField.get(eachField));
}
// Return the Lead record
return record;
}
public abstract Schema.SObjectType getSObjectType();
}
and a lead-specific subclass:
global class LeadFactory extends GenericFactory{
public override Schema.SObjectType getSObjectType(){
return Lead.SObjectType;
}
public Lead makeLead(Map<SObjectField, Object> valuesByField){
return (Lead) this.makeRecord(valuesByField);
}
}
This is about as clean as you can get without doing the type casts in the calling code.
ca_peterson's example is a great start, however how would you handle changes in org requirements, validation rules, etc that would cause your test factory to fail, and how soon would you know they fail?. Not to mention the code needed to add new object, etc. To each their own.
We start using the SEED for Test methods package both within our test factory and standalone, and it handles all that for use. Never have to remember what fields are require to populate in order to create an object, reducing dev time as the line to create an object is simply obj.createRecord(Account.sObjectType);
and everything is taken care of, and if an org change occurs SEED picks it up automatically and the test continue to run without fail.
Not really a direct answer but another potential way to solve the situation.