I would appreciate information or examples about how to correctly test code that uses DateTimeOffset instances. I know the tests have to be deterministic.
So, how would one isolate the application from the DateTimeOffset classes ? I would, of course, like to be able to use a fake DateTimeOffset.Now, etc.
In my tests, should I be using something like:
var myDate = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-3));
Or would I instead be using a wrapper class like MyCustomDateTimeOffset ? Should I not use DateTimeOffset at all in my code and use a wrapper instead?
Controller methods should be unit tested using assert for REST HTTP Status code. Use the HttpStatusCode enum type to Assert the responses. Assert. IsType<OkObjectResult>(result);
Unit testing involves testing a part of an application in isolation from its infrastructure and dependencies. When you unit test controller logic, only the content of a single action or method is tested, not the behavior of its dependencies or of the framework itself.
As the fundamentals theorem says:
We can solve any problem by introducing an extra level of indirection.
You don't really need a wrapper, all you need is to avoid DateTimeOffset.Now
/DateTimeOffset.UtcNow
.
Here are a few ways you could handle that:
If you use dependency injection, write an IClock
interface which exposes the Now
/UtcNow
properties.
public interface IClock
{
DateTimeOffset Now { get; }
DateTimeOffset UtcNow { get; }
}
internal class Clock : IClock
{
public DateTimeOffset Now => DateTimeOffset.Now;
public DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
}
In your tests, you just mock the interface as you wish.
If you'd rather keep using a static property, write a static type, let's say Clock
, and use that.
public static class Clock
{
internal static Func<DateTimeOffset> DateTimeOffsetProvider { get; set; }
= () => DateTimeOffset.Now;
public static DateTimeOffset Now => DateTimeOffsetProvider();
public static DateTimeOffset UtcNow => DateTimeOffsetProvider().ToUniversalTime();
}
In your tests, you can substitute DateTimeOffsetProvider
.
Here's a .NET 2 version:
public static class Clock
{
internal delegate DateTimeOffset DateTimeOffsetProviderDelegate();
internal static DateTimeOffsetProviderDelegate DateTimeOffsetProvider { get; set; }
public static DateTimeOffset Now { get { return DateTimeOffsetProvider(); } }
public static DateTimeOffset UtcNow { get { return DateTimeOffsetProvider().ToUniversalTime(); } }
static Clock()
{
DateTimeOffsetProvider = delegate() { return DateTimeOffset.Now; };
}
}
As you won't know the value of DateTimeOffSet.Now, then all you can't assert that DateTimeOffSet.Now equals a value.
You probably should refactor to use one of two methods:
DI means instead of having the method determine the date, you pass it in.
This method . . .
public void DoSomething()
{
var now = DateTimeOffSet.Now;
// Do other stuff with the date
}
. . . would change to this method
public void DoSomething(DateTimeOffSet dtos)
{
// Do other stuff with the date
}
Your other option (although in the end you would use DI with this too) is to create an Interface and a Wrapper. Then use you the interface in your object instead of a concrete DateTimeOffSet, so you can then use MOQ or other testing library to moq the interface. Check out SystemWrapper (https://github.com/jozefizso/SystemWrapper) project for an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With