Reputation: 535
So I'm writing a cache system (not too complicated, but it has very nice semantics) with a ttl (time to live) for items.
Of course the ttl must be unit tested, but since one can't inject a new implementaton of "IDateTime" or "ITimeSpan" in C# (because there is no such thing), how would you go about that?
Write a new component "IDateTimeProvider" and "DateTimeProvider" first, which one can mockup then?
Isn't reimplementing parts of the .NET runtime library... overkill?
Edit: Thank you all for your amazing answers! I know now exactly what I'm going to do!
Upvotes: 6
Views: 2359
Reputation: 29861
I usually use a variation of Ayende's solution.
public static class SystemTime
{
public static Func<DateTime> DateProvider = () => DateTime.Now;
public static DateTime Now { get { return DateProvider(); } }
}
In the code under test you can now use SystemTime.Now to get the current time:
var currentTime = SystemTime.Now;
And in the test you can set the current time to a known value:
SystemTime.DateProvider = () => new DateTime(2010,6,25);
Upvotes: 6
Reputation: 977
You might want to see this question:
How do I MOQ the System.IO.FileInfo class... or any other class without an interface?
In a nutshell you'll either need to make a wrapper class yourself, or use a library that already provides wrapper classes for DateTime, like SystemWrapper.
Upvotes: 4
Reputation: 41519
If you're having trouble inventing some mockup object, I think it'ld be good to rethink the testability of your component.
Maybe the ttl logic should be testable on it's own, somewhat like this:
TTLlogic l = new TTLLogic( 10 );
DateTime startdate = now();
Object item=new String();
l.addItem( startdate, item );
l.setTime( startdate.addSeconds( 5 ) );
assert( l.items().contains( item ) );
l.setTime( startdate.addSeconds( 10 ) );
assert( l.items().empty() );
Upvotes: 2
Reputation: 3940
An IDateTime provider might prove useful in other ways -- if your cache is to be used between client and server apps running on separate machines, you will one one single time-source for both machines (usually the server) otherwise the times may be out of step. I you use the IDateTimeProvider interface everywhere, then the client can use a version that gets the time from the server.
You would get that plus the Unit-testing de-coupling.
Upvotes: 2
Reputation: 2684
how would writing an IDateTimeProvider be reimplementing parts of the .Net Framework?
You'd just have two implementations, one that returns DateTime.Now and another that returns a value you specified before.
Upvotes: 4