0
  1. I have a class which takes any record id and returns fields name and it's values as well as relationship record's values.

  2. Now to write a Test class, i have to create a record.

  3. I can try with inserting Account record, but If Account have mandatory fields other than "Name" in the destination/Installing environment.Because we don't know what fields are there in every Organization.

  4. what type of record can i create for this Use case.

Any possibility ?

2 Answers 2

5

Maybe you could calculate "on the fly" your account fields using Map<String, Schema.SObjectField> mapFields = Schema.getGlobalDescribe().get('Account').getDescribe().fields.getMap(); then you just need to use isNillable() method over each field to know if they are required and if true just fill them, then call your test

1
  • Oooh nice. I hadn't really looked at isNillable() before. What a strange way for Salesforce to communicate a 'required' field.
    – Nick C
    Commented Jul 21, 2016 at 13:08
2

There is an inherent flaw in simply checking if the field is nillable. Sometimes the requirement is more nuanced. Maybe a Validation Rule is in place to ensure a specific Date field can only be in the future, or makes one of a collection of fields required. There are infinite variations on how Validation Rules affect this scenario. You could also have validations applied via Apex Trigger in more complex cases.

You also need to think about fields which are unique. If you create records in bulk, this consideration is just as important. You may also end up struggling with required Lookup fields, strict picklists, and length constraints.


I wrote a tool called SObjectFactory and had to work through some of these concerns. You can see it on GitHub here. My pattern was to implement a RequiredFieldsCache and just populate it manually. The basic idea:

@IsTest
public class RequiredFieldsCache
{
    public static Map<SObjectField, Object> get(SObjectType sObjectType)
    {
        return cache.containsKey(sObjectType) ?
            cache.get(sObjectType) : new Map<SObjectField, Object>();
    }

    static Map<SObjectType, Map<SObjectField, Object>> cache =
        new Map<SObjectType, Map<SObjectField, Object>>
    {
        Account.sObjectType => Map<SObjectField, Object>
        {
            Account.Name => 'ACME'
        }
    }
}

In a Managed Package, you're going to have to find a way to make this mechanism configurable, likely via Custom Metadata Types. You could build out this cache dynamically using isNillable() and isUnique(), then fill in the gaps with the metadata object. You may need to build out your Custom Metadata Type to enable dynamic provider values in addition to more vanilla schemes.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .