TL;DR
How can I write to non-writeable SObject fields while running apex unit tests?
Background
While creating unit tests that check a method's functionality independent of any DML functions, it is sometimes necessary (or at least very helpful) to set field values on SObjects.
Example:
Lets say I have the class shown below. (In this example, my org's Account
object has a formula field Owners_Email_Address__c
which, returns the email address of the Owner of the Account.)
public with sharing class MyClass{
public static String getParentAccountsOwnerEmail(Contact myContact){
return (String)myContact.Account.get('Owners_Email_Address__c');
}
public static Boolean createdDateMatchesValue(Contact myContact, Date expectedCreatedDate){
return myContact.CreatedDate == expectedCreatedDate;
}
}
While writing my apex class, I could get both the Owners_Email_Address__c
and CreatedDate
values populated, but doing so would require multiple DML operations:
- create and insert User for Account owner
- create and insert Account with new User as Owner
- create and insert Contact then use
Test.setCreatedDate()
to specify a date (if something different than the current date needed)
While this is all fine, it often runs into other issues that cause additional considerations and overhead, such as:
- Making sure other required field on each desired record to insert are properly set
- Verifying that a desired field wasn't changed during the DML operation due to another automation
As an org grows and its automations grow, this can make inserting just a few records for a test quite a headache.
Question
When DML operations aren't necessary for a test (such as when building unit tests that should only test the functionality of a specific function), how can I bypass the need to have multiple DML operations to populate non-writeable fields?