Our programming journey often presents us with intricate dependencies that require clever workarounds. A commonly overlooked one is system time. This edition tackles such dependencies to create testable, robust, and maintainable code.
Many of us are guilty of directly using DateTime.Now
or DateTimeOffset.Now
in our code, which unfortunately introduces testing complications. Let's uncover the challenges that come with this:
Testing time-dependent logic - When our code relies on the current time or date for tasks like generating daily reports or sending batch emails, controlling the "current" time for testability becomes an uphill task.
Creating repeatable tests - Ideally, tests should be consistent, executing the same way irrespective of when they're run. Using DateTime
or DateTimeOffset
directly couples our code to the system clock, potentially leading to inconsistent test results.
So, what's the workaround? Simple - we abstract the system time behind an interface or use a service to fetch the current time. This way, we can substitute the real service with a mock or stub during tests, providing a hard-coded time instead.
And here comes the superhero - NodaTime library by the Chuck Norris of programming - Jon Skeet, to the rescue! NodaTime
offers the IClock
interface, representing a source of time information. In production, we can use SystemClock.Instance
which fetches the actual system clock. For testing purposes, we have FakeClock
, allowing manual control over time.
By leveraging NodaTime, we make our code more testable, robust, and maintainable. A worthy consideration as an alternative to DateTime
and DateTimeOffset
for handling date and time in C# projects.
If introducing a third-party dependency is a concern, you can achieve similar results by wrapping usage behind an interface of your own.
A pro tip - try applying the same approach when creating new GUIDs. It enhances control, making your tests more predictable and repeatable.