Skip to content

Mock Field Reader - Learn how to use dependency injection to mock non-writable fields, such as formula fields and child relationships in your tests.

Notifications You must be signed in to change notification settings

gitmatheus/MockFieldReader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mock Field Reader

apex_code_blocks

Learn how to use dependency injection to mock read-only fields, such as formula fields and child relationships in your tests.


A while ago we explored the Mock Data Layer Pattern, which allows us to mock virtually any relationships between records within your tests. This is especially handy when trying to improve the performance of these tests - more details on matheus.dev.

Now, how can we mock formula fields and read-only child relationships if they are, well, read-only fields? 🤔

Mocking values in read-only fields

For this exploratory project, we will use a not-so-realistic scenario with parent and child accounts, but the intent is to create a test for the Account Trigger Handler that will use a Mock Field Reader and a Mock Data Layer.

The Mock Field Reader will be used so we can mock two read-only fields on the Account object.

  • Child_Accounts__r, a read-only child relationship on the parent record
  • External_URL__c, a formula field on the child record

The trigger handler logic will update the following field:

  • Parent.Latest_Child_URL__c

Based on the following formula field:

  • Child.External_URL__c

⚙️ Files used in this project

force-app
    main
        default
            classes
                ◦ AccountTriggerHandler
                ◦ AccountTriggerHandlerTest
                ◦ FieldReader
                ◦ IFieldReader
                ◦ MockFieldReader
                ◦ TestUtils
            triggers
                ◦ AccountTrigger

⚡️ Show me the code!

Getters

To respect the injected dependency, these methods must be present on both the real instance of the field reader ( FieldReader ) and the mock instance of the field reader ( MockFieldReader ).

public Object getFieldValue(SObject record, String fieldName)

This method is used to retrieve the mock values of formula fields. It returns an Object that can later be casted as different types, such as String, Number, Id, etc.

public SObject getFieldRecord(SObject record, String fieldName)

This method is used to retrieve the mock values that represent a single record. It returns an SObject.

public List getFieldRecords(SObject record, String fieldName)

This method is used to retrieve the mock values that represent a list of records, such as a child relationship. It returns a list of SObjects.

Setter

There's only one method used to set the values, and it's only present on the mock instance of the field reader ( MockFieldReader ).

public void addValueToField(SObject record, String field, Object value)

This method adds the field/value pair to a map of mocked values, indexed by the record Id.

Examples

In this repository you will find a trigger handler class and its respective test class with the usage of this Mock Field Reader.

Snippet from the AccountTriggerHandler: pay attention to how the following methods are being used:

fieldReader.getFieldRecords(parentAndChildAccount, 'Child_Accounts__r');

fieldReader.getFieldValue(latestChild, 'External_URL__c');

// Snippet from the AccountTriggerHandler

    ...

    // Child_Accounts__r is a nonwritable child relationship
    // Uses the field reader to retrieve the list of child records:
    List<Account> childRecords =
        fieldReader.getFieldRecords(parentAndChildAccount, 'Child_Accounts__r');

    if (childRecords != null && !childRecords.isEmpty()) {    
        Account latestChild = childRecords[0];

        // Updates the field Latest Child URL with the value from External_URL__c
        // External_URL__c is a formula field (nonwritable string)
        newRecord.Latest_Child_URL__c = 
            (String)fieldReader.getFieldValue(latestChild, 'External_URL__c');
    } 


And in the AccountTriggerHandlerTest you can see how these read-only fields can be mocked, using the method addValueToField:

    // Snippet from AccountTriggerHandlerTest

    ...
    mockDataLayer = new MockDataLayer();
    mockFieldReader = new MockFieldReader();
    ...

    // First, the formula field on the child object:
    mockFieldReader.addValueToField(
        mockDataLayer.childAccount,
        'External_URL__c',
        expectedURL
    );

    // Then, the nonwritable child relationship
    mockFieldReader.addValueToField(
        mockDataLayer.parentAccount, 
        'Child_Accounts__r', 
        new List<Account>{mockDataLayer.childAccount}
    );

With this code and the Mock Field Reader, it becomes easy to mock read-only fields used in the tests.

I hope that helps!

About

Mock Field Reader - Learn how to use dependency injection to mock non-writable fields, such as formula fields and child relationships in your tests.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages