The Dark Side of Faking DateTime.Now

Add a feature and see the support calls comes in.

Our new feature of faking DateTime.Now is causing some issues. You can see Dennis’ post and Soon Hui’s post which are basically point to the same problem. What happened is that we caused a breaking change without realizing it.

Let’s look at what happened before. I’ll use Dennis’ example here:

Isolate.Verify.WasCalledWithAnyArguments(() => someObject.ProcessDate = DateTime.Now);

What we have inside the delegate looks like that:

someObject.set_ProcessDate(DateTime.Now)

When we say Isolator doesn’t support mscorlib, here’s what we mean: All mscorlib types are not intercepted by Isolator, and run outside its scope. Because we can’t intercept the calls, we can’t change their behavior.

So before 5.3.1, what would happen is that Isolator would intercept the method call to the ProcessDate setter, but not for DateTime.Now. For Isolator, it would look like a concrete value was set.

But this has now changed. Now Isolator intercepts two methods, which are not in a chain. Isolator’s AAA API has a limitation, that they don’t handle well more than a single chain. So the test that has previously passed, because there was just a single call inside, now breaks, because there are two now. And of course, that’s why Dennis’ solution works. He got the DateTime.Now outside the Verify clause, and everything returned to normal.

We admit: we break stuff. We don’t mean to. Not on purpose, anyway. But the more we delve into mscorlib land, these things may happen. It’s part of the product’s evolution. However your feedback is valuable – we learn how you write tests, then we make great products helping you write them better.

  • Robert

    I've avoided the issue of faking DateTime.Now by pushing it back one level into a method I COULD fake. I build a helper method:

    GetNow() { return DateTime.Now; }

    In my test code, I can fake GetNow() to return my test value, rather than needing to fake DateTime.Now itself.

  • Gil Zilberfeld

    Robert,

    That's how we used to do it.
    But now you don't have to put another abstraction in your code just for testing.

TOP