Is it possible to test apex that relies on field history tracking?

I have some code that relies on field history tracking by querying the History for a custom object. This works fine, but it appears that the history records aren’t created during the test so none of my tests will pass.

Answer

I had a suspicion (remember reading somewhere) that Field History Tracking cannot be tested in a Unit Test Class.

A bit of Developer Board surfing threw up this post which confirmed that since none of the data is actually committed during a Unit Test, its not possible to Unit Test Field History Tracking.
http://boards.developerforce.com/t5/Visualforce-Development/Unit-Testing-and-History-Table/td-p/142422

The History tables are ReadOnly, coz I’m guessing they’re a little bit like the Salesforce System Fields. To maintain the integrity of the audit trail, they’re locked to writes. To be able to write our own history records, we’d need to roll our own History Mechanism, with an object and a trigger

To confirm this suspicion, I quickly wrote this test class : (after turning on Field History Tracking on the Type field)

@isTest
public class AccountTest {
@isTest
    private static void  testOne(){
     Account acc = new Account(Name = 'Hello', Type='Other');
     insert acc;
     Test.startTest();
acc.Type = 'Prospect';
update acc;
Test.stopTest();

AccountHistory[] ah =  [Select AccountId, Field, OldValue, NewValue from AccountHistory where AccountId = :acc.Id];
System.debug('ACC HIST IS ' + ah);
System.assertEQuals(1, ah.size());   //ASSERTION FAILS              
    }

}

(As an aside, this also fails when executed from Execute Anonymous or when run on load from a VF Page. It would seem that you can’t query for the History from the same execution context. Inserting the account first, and then separately updating the Type seems to yield History from execute anonymous / vf)

To make your tests with work sufficient coverage, you can make use of the Test.isRunningTest to return a mock AccountHistory response as below (although OldValue and NewValue will be null as they are not writeable)

public class AccountHistoryUtil {

@isTest
    private static void  testOne(){
    Account acc = new Account(Name = 'Hello World' + Datetime.now());
    insert acc;

    Test.startTest();

    AccountHistoryUtil accHistClass = new AccountHistoryUtil();

    accHistClass.processAccountUpdate(acc.Id);

    AccountHistory[] accHist = accHistClass.retrieveAccountHistory(acc.Id);
    Test.stopTest();
    System.assertEQuals(1, accHist.size());                
    }


    public void processAccountUpdate(Id accountId){
       Account acc = new Account(Id = accountId, Type = 'Other');
       update acc; 

    }

    public AccountHistory[] retrieveAccountHistory(Id accountId){
     List<AccountHistory> ah;
     if(Test.isRunningTest()){  //if TEST, create dummy AccountHistory
         ah = new List<AccountHistory>{}; //OldValue, NewValue not writeable
         ah.add(new AccountHistory(AccountId=accountId, Field='Type'));
     }
     else 
         ah=  [Select AccountId, Field, OldValue, NewValue from AccountHistory where AccountId = :accountId];


     return ah;
    }
}

Attribution
Source : Link , Question Author : jwolf , Answer Author : techtrekker

Leave a Comment