How do you test code that depends on DateTime.Now or randomness?

Unit Testing & TDD Practices Intermediate 2–3 Yrs3–5 Yrs Coding 1 min read

Quick Answer

Don't call DateTime.Now / Random / Guid.NewGuid() directly — inject them. Use an IClock abstraction (or .NET 8's TimeProvider) and a seeded or injected random source. Tests then control “now” and get deterministic results.

The rule is not to call DateTime.Now, new Random() or Guid.NewGuid() directly in code you want to test — inject them instead. I use an IClock interface with a UtcNow property; production gives the real time, the test gives a fixed one. .NET 8 has TimeProvider built in for exactly this, with a fake version that lets tests advance the clock. Same idea for randomness — a seed or a small abstraction — so the test is deterministic.

  • interface IClock { DateTimeOffset UtcNow { get; } } — production returns DateTimeOffset.UtcNow; test returns a fixed value.
  • .NET 8+: TimeProvider is the built-in abstraction; FakeTimeProvider (from Microsoft.Extensions.TimeProvider.Testing) lets tests advance time.
  • Same for randomness: pass an int seed or a Func<int>, or an interface, so a test can make it predictable.
  • This is the “don't reach out, pass in” rule — it keeps the method pure and testable.