5

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

  • I think scheduled classes may start right away when they're run as part of a test. I'll see if I can chase down a reference for that. – Jagular Dec 30 '14 at 23:19
  • Do you really want to test the clock ticking ? – Martin Dec 31 '14 at 8:36
8

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.

  • thanks - I used the solution when testing automatic renewal batch jobs that needed leap year use cases – cropredy Dec 31 '14 at 18:49
  • the methods should be public static, just an FYI – TemporaryFix Jan 4 '17 at 21:29
  • @Programatic - no kidding; I revised the implementation as well to use properties as per abd3721 since that is a cleaner implementation – cropredy Jan 4 '17 at 21:35
3

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);
2

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;
}}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.