Emulation of date and time on Force.com

The one of the most significant things in testing is an ability to repeat your tests any number of times with the same state of environment. What is an environment state and how can we provide an ability to emulate the same state each time?

Test environment includes the following components:

  • Configuration (The state of the configuration and system parameters should be the same)
  • Data level (it’s all data which needed for tests)
  • Time (many operations depend on a time)

Sure, it’s pretty simple if we’re talking about a data level as well as a configuration. In these areas we can reload a new data set each time if old data set will be broken. But what about a time? Here we have a strongly limitation but it might be avoided. So, we can implement the following solution on the top of system date/time. Such approach will be extremely useful for QA team. We’ll create a custom setting which will allow us to enable the time emulation, set a time shift and a fixed current time. So, let’s go ahead.

Go to Setup → Develop → Custom Settings → Create and create a new custom setting with hierarchy type. In my example I named it Date Time Configuration (DateTimeConfiguration__c) but you can name it as you want. But be aware that you need to change the code below for using your setting name.

Ok, let’s add a few fields. I created fields:

  • Boolean isEmulationEnabled__c,
  • DateTime emulatedDT__c,
  • Integer dateShift__c.

It’s enough for our purposes. So, we’ve finished with the creation of needed config and now we can implement a code.

EDateTime.cls

public class EDateTime {
    private static DateTimeConfiguration__c dtConfig;
    private static DateTime currentDateTime {
        get {
            currentDateTime = System.now();
            // on Production we always use real time
            if (!Utils.isProduction) {
                // Caching DateTime configuration
                if (dtConfig == null) {
                    dtConfig = DateTimeConfiguration__c.getInstance();
                }
                // if configuration exists and emulation is enabled we define new date and time
                if (dtConfig != null && dtConfig.isEmulationEnabled__c) {
                    if (dtConfig.dateShift__c != null ) {
                        currentDateTime = System.now().addDays(dtConfig.dateShift__c.intValue());
                    } else {
                        currentDateTime = dtConfig.emulatedDT__c;
                    }
                }
            }
        return currentDateTime;
        }
    }

    public static Date today() {
       return currentDateTime.date();
    }

    public static DateTime now() {
       return currentDateTime;
    }
}

Utils.cls

public static Boolean isProduction {
    get {
    // The Prod Org Id is permanent and can be hardcoded
        return (UserInfo.getOrganizationId() ==00DE0000000bplPMAX’ );
    }
    private set;
}

Now you need to replace all invocation of System.now() in your code by a new one method EDateTime.now(), as well as System.today() by EDateTime.today(). Now you can reproduce your tests with the same date and time as many times as you want. It might be extremely useful if you’re testing a time-based solutions. That’s it.

[apex][date/time][date/time emulation][force.com][salesforce]