How to Test Apex code with Field History Tracking?

Question
In Salesforce, testing Apex code that relies on field history tracking can be challenging because field history records are not automatically created during tests. This issue arises when the code queries history records, such as those for custom objects. Although the code works in production, the tests fail because no history records are available by default in the test context.
Answer
Testing Apex code that relies on field history tracking can be tricky, especially because history records are not automatically created during unit tests. However, there are ways to simulate history records and test your code accordingly.
One approach is to use Test.loadData()
to load history data from a static resource, such as a CSV file, which contains mock history records. This allows you to simulate the field history tracking behavior for custom objects. You can then inject these records into your test methods.
Here’s an example of how to load and test history records:
Example Test Method:
@isTest
static void testLoadHistory() {
List<Circuit__History> cs = Test.loadData(Circuit__History.SObjectType, 'TestCircuitHistoryData');
system.debug(cs); // This prints the loaded history records for inspection
}
In this example:
Test.loadData(Circuit__History.SObjectType, 'TestCircuitHistoryData')
loads history records for a custom objectCircuit__c
from a static CSV file namedTestCircuitHistoryData
.system.debug(cs)
prints the loaded records to the debug log, so you can inspect the data.
See also: Salesforce Apex Interview Questions
Refactoring Your Apex Code for Testing:
If your original Apex code queries for field history data, you will need to refactor it slightly to allow injecting history data into the method. Here’s an example of refactoring the method to accept history data as an argument:
public void operateOnHistory(List<Circuit__History> history) {
for (Circuit__History ch : history) {
if (ch.Field == 'Card__c' && ch.OldValue != 'trouble') {
// Your logic here
}
}
}
This refactor allows you to pass in mock data (such as the history records you loaded with Test.loadData()
), making your method more testable.
Complete Test Class Example:
Now, here’s how you can use Test.loadData()
in a complete test class:
@isTest
private class HistoryTest {
static List<Circuit__History> circuitHistory;
static void setup() {
// Load the mock history data from the static resource
circuitHistory = Test.loadData(Circuit__History.SObjectType, 'TestCircuitHistoryData');
}
@isTest
static void testLoadedHistory() {
MyCircuitClass mcc = new MyCircuitClass();
// Create a map of Circuit records based on the ParentId from history
Map<Id, Circuit__c> circuitsMap = new Map<Id, Circuit__c>();
for (Circuit__History ch : circuitHistory) {
circuitsMap.put(ch.ParentId, new Circuit__c(Id = ch.ParentId));
}
mcc.circuitsMap = circuitsMap;
test.startTest();
mcc.operateOnHistory(circuitHistory); // Inject the mock history data
test.stopTest();
}
}
Explanation of the Test Class:
- Loading the history data: In the
setup()
method,Test.loadData(Circuit__History.SObjectType, 'TestCircuitHistoryData')
loads the history records from the CSV file stored as a static resource. - Mapping circuit records: In the
testLoadedHistory()
method, thecircuitHistory
is iterated, and a map ofCircuit__c
records is created using theParentId
field from the history data. This map is injected into the class under test (MyCircuitClass
). - Injecting and testing: The
operateOnHistory()
method ofMyCircuitClass
is called with the mock history records. This allows you to test the logic that depends on history data, without relying on actual field history in the org. - Test boundaries:
test.startTest()
andtest.stopTest()
are used to mark the start and end of the test, ensuring that performance is properly measured and the test execution is isolated.
By following this approach, you can test Apex code that depends on field history tracking without relying on real field history records in Salesforce. The key is to simulate the history records using static resources and inject them into the test code, enabling you to test your business logic with mock data.
See also: List Class in Salesforce Apex
Job-Oriented Salesforce Training with 100% Money Back Assurance
Our Salesforce Course is structured to provide a deep understanding of the Salesforce platform, equipping you with the essential skills to excel in the CRM industry. This program covers fundamental modules like Salesforce Admin, Developer, and AI, combining theoretical knowledge with hands-on practice. By engaging in real-world projects and practical assignments, you’ll develop the expertise to solve complex business challenges using Salesforce solutions. Our expert trainers ensure you gain both technical proficiency and industry insights to succeed in the Salesforce ecosystem.
Beyond technical learning, our Salesforce Training in Dallas includes personalized mentorship, certification assistance, and interview preparation to enhance your career prospects. You’ll have access to extensive study resources, real-world project experience, and dedicated support throughout the program. By the end of the course, you’ll be fully prepared for certification exams and possess the problem-solving skills that employers seek. Start your Salesforce journey with us and unlock new career opportunities—Sign up for a Free Demo today!