DDD: Entity Injection and Mocking Time

[UPDATE: I have created an open source library based upon the concepts found below.]

In my early experience with DDD, I loved injecting dependencies into my domain entities. I have since repented. The one downright nasty dependency that we could never quite slip away from was…time. That's right, temporal couplings. Well, not exactly. Instead, we had to couple to an object that provides the current time.

Initially we had used a "TimeService", basically just a service that you would inject (ugh) into your entities so that they could query the current time.

We've kicked around a few alternatives because we have always wanted to stay away from System.DateTime.UtcNow—mocking that particular class isn't fun.

Udi Dahan has written about fully encapsulated domain models. His third take on the subject was very insightful, but I couldn't bring myself to use the static singleton reference he had for publishing events. At first glance, this is completely unrelated to what I'm talking about.

Today when I read Mark Needham's post regarding testability and DateTime, I thought back to the days when we hit issues with that. But then I saw a comment by Ryan Roberts. He showed his solution for the problem they had with time:

I use a ..static DomainTime.Instance shim to control datetime in tests.

Ends up with something like

using(DomainTime.Is(new(DateTime(2003,10,10))
{
var model = SomeRandomModel.JustTheUsualMethod();
DomainTime.HasBeen(new TimeSpan(0,0,0,1));

Assert.AreEqual(..)
}

It's simple and brilliant. Just use a static singleton instance (like Udi does, but for time) that you can easily mock and do it within the context of a using statement. In this manner, we can control the value of "now" within our tests or our code.

UPDATE: I've read both of these articles previously, but I'm referencing them here because they have interesting and relevant discussion: