Using time? Inject a clock.

Your favourite language’s way to get the current time (e.g. new Date() in JS or DateTimeOffset.Now in C#) is lovely. It’s also a nasty global singleton, in that you can’t mock or stub it from tests.

The problem with directly referring to “the current time” from application code is that you often end up doing Thread.Sleep(...)s all over your automated test code. This makes tests slow and brittle. Now, an automated test with some busy waiting an ugly thread magic is better than no test at all, but if you have the chance, better avoid it.

I found that, in nearly all cases, it helps to inject a clock:

public interface IClock
    DateTimeOffset Now { get; }

This interface will allow you to very easily simulate time-derived behaviour. I usually use a RealClock that the application uses, and a FakeClock used by tests. They’re ridiculously simple too:

public class RealClock : IClock
    public DateTimeOffset Now { get { return DateTimeOffset.Now; } }

public class FakeClock
    private DateTimeOffset now;

<pre><code>public FakeClock(DateTimeOffset startTime)
    now = startTime;

public FakeClock()
    now = DateTimeOffset.Now;

/// &amp;lt;summary&amp;gt;
/// Gets or updates the clock's current time.
/// &amp;lt;/summary&amp;gt;
public DateTimeOffset Now
    get { return now; }
        if (value &amp;lt; now)
            throw new InvalidOperationException(&amp;quot;Can&#039;t decrease time.&amp;quot;);

        now = value;


The FakeClock could have been a lot simpler, but I choose to enforce that time never rewinds. Code assumes this more often than you'd think, and there's nothing wrong with that.

Using an injected clock, you get real nice test code, for anything that depends on time changes, such as UI animations or hardware simulators.

Imagine a screen that has an alarm trigger, which when activate is on for exactly 5 minutes:

public void AlarmShouldBeVisibleFrom5Minutes()
    var clock = new FakeClock();
    var screen = new SomethingScreen();


// verify that the alarm is still going 1 second before
// the 5 minutes have passed.
clock.Now += TimeSpan.FromSeconds(299);

clock.Now += TimeSpan.FromSeconds(1);


The key point is, of course, in code like clock.Now += [something];. Even if you hate mutable state, you have to accept that time is inherently mutable. Simply updating the time from automated tests allows for a pretty simple way to deal with that.

10 thoughts on “Using time? Inject a clock.

  1. +1. It also works beautifully with bigger units of time, btw: for my soccer score prediction project, a new season starts in August. I used an injected clock to test the switch from one season to the next.

  2. Woohoo! A first comment! I’m so flattered 🙂

    Good point! Another advantage to working this way is that it encourages you to implement “triggered” events in a more functional way. For example, a game could automatically start a new tournament each week. You can run a scheduled task for this, but you can also make the `currentGame` depend on a clock, and lazily create any data storage that it may depend on, upon first invocation.

    This is not always practical, but it does yield code that is significantly easier to test. Not always simpler code though, so use with caution.

  3. You’re welcome :). (I have to remember to check the “Notify me of follow-up comments” box, btw…)

    You’re right, the code doesn’t always get simpler, but I would be willing to defend the position that, if your code is sufficiently complex to have unit tests, it’s worth doing this. In other words: for throw-away code it’s fine to call new Date(), but in all other cases, use a clock.

  4. Hello, random person on the internet!

    For these kind of situations I feel that having an IClock abstraction can be a bit too heavy (needs to be passed in or injected, etc), and something like a static class containing “public static Func UtcNow = () => DateTime.UtcNow;”

    That Func is trivial to overwrite in your unit tests, but doesn’t require any big refactoring.

    • Hello, random lurker!

      Hm, admittedly I actually like that idea. The problem with it is that you’re changing global state, and a mistake there might screw up tests, or change the results depending on the order in which tests run.

      Actually, I wouldn’t be unhappy with some sort of “test local storage”. You could emulate that with thread local storage and a test runner that runs each test in its own thread. I doubt the performance implications of that would be significant.

      By the way, DHH agrees with you

      • Uh-oh, before I know it I’ll have a handlebar mustache and skinny jeans!

        Something like “Test local storage” is interesting and in some ways it can already be done with DI if you use a feature that’s usually called a child container (or nested container). Hooking that up with your unit test framework’s test lifecycle you spin one up, use that child container for your test, and dispose of it again. It’s kind of like how you can wrap your database tests in a transaction and roll back at the end: Other threads running other tests don’t see the changes and the end everything is neatly back to where it was.

  5. Good idea using a Clock interface — you just need to remember to use your homegrown Clock object instead of the canonical one, or your tests will fail mysteriously.

    BTW, there might be a case for using a rewinding clock during tests: if you build licensing software or user rights management stuff, you want to make sure that users can’t easily circumvent
    it by setting the system clock back to some earlier date, so you want to use a TestClock that does just that.

    (nitpick: you might want to weed out some escape artefacts in your code: there are some < pre > < code > tags visible, and your comments contain HTML stuff like &lt;.)

    • Hey, good one! And come to think of it, making classes, only intended for use in tests, that enforce arbitrary assumptions on the user might be a bit over the top anyway. In fact, any decent mocking framework could probably provide the same functionality more flexibly.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s