There is only one thing worse than having no tests and that is having flaky tests. You know, tests that sometimes fail and sometimes succeed when the code itself didn't change. One of the biggest reasons this can happen is when your tests have time related logic.
My tests succeed on Monday but not during the weekend.
Sidenote: there is a cool Azure DevOps feature specifically to handle and fix flaky tests. Anyway that is not the topic of this post.
In .NET 8 Microsoft tried to fix this by introducing a new time abstraction API. Instead of directly calling DateTime.Now
or DateTime.UtcNow
inside your code, you can now use the TimeProvider class and ITimer interface. Together they offer time abstraction functionality, facilitating the simulation of time in testing scenarios.
Remark: Microsoft was so nice to backport these APIs and made them available in a separate NuGet package Microsoft.Bcl.TimeProvider.
So now we can update our code to use the TimeProvider class instead:
If we now want to test our code we can use the Microsoft.Extensions.TimeProvider.Testing package. This includes a TimeProvider
implementation called FakeTimeProvider
which gives us explicit control over the flow of time.
An example:
These new abstractions can also be used in asynchronous program execution thanks to some new overloads:
Nice!