Salesforce: Is there any way to set System time in test class

So I have a trigger and a schedule class. The trigger will fire upon update on an object and schedule a job which will execute the scheduled class. There is some logic in the trigger related to non-working hours, weekends and holidays. It will usually schedule the job 1 hour after insert (due to business requirement). but if insert happens over the weekend, afterhours, or holidays. It will schedule the next business day 8am.

My problem is my test class does not cover everything. I insert the object in test class, and depends on what time I run the test, it will cover different part. Like if I run during business hours, the weekend, holiday logic doesn’t get covered, etc.

My question is there anyway in test class we can set the Datetime.Now to any date and time we want? thanks very much

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

A solution to this is as follows:

//  -----------------------------------------------
//  now     : getter/setter to have testemthod-driven different values for now; see also today
//  -----------------------------------------------
public static DateTime now      {get {return now == null ? DateTime.now() : now;} set;}

//  -----------------------------------------------
//  today : getter/setter to have testemthod-driven different values for today; see also now
//  -----------------------------------------------
public static Date today {get {return today == null ? Date.today() : today;} set;}

Then your trigger needs to always get the current time by using Util.now. In PROD, it will always return the true “now” time.

But your testmethods can call Util.now = testTime; before doing DML on the triggered SObject. Your trigger code will then get a fake datetime so you can verify that your CronTrigger is properly setup.

Method 2

Inspired by Crop1645’s answer, here’s an answer in the form of a single property accessor:

/**
 * Allows the current Date and Time to be set/spoofed
 * this is generally only useful for test classes
 */
public static DateTime now {
  get {
    return (now == null) ? DateTime.now() : now;
  }
  set;
}

This allows you to run:

system.assertEquals(DateTime.now(), now);
now = DateTime.now().addYears(-1);
system.assertNotEquals(DateTime.now(), now);

Method 3

Idea for enhancement of previous solutions, to prevent incorrect usage of now and today in production environment and enable changes only for unit tests:

public class ForceUtils {

@TestVisible
private static Datetime now;

@TestVisible
private static Date today;

public static Datetime now() {
    return now == null ? Datetime.now() : now;
}

public static Date today() {
    return today == null ? Date.today() : today;
}}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x