I have this method which is dependent on current date. It checks if today is Sun, Mon, Tue or Wed, then it gives 5 days of lead time for arrival of shipped items. If its Thu
You need to pass the current date in as a parameter:
private DateTime GetEstimatedArrivalDate(DateTime currentDate)
{
DateTime estimatedDate;
if (currentDate.DayOfWeek >= DayOfWeek.Thursday)
{
estimatedDate = currentDate.AddDays(6);
}
else
{
estimatedDate = currentDate.AddDays(5);
}
return estimatedDate;
}
In real code you call it like this:
DateTime estimatedDate = GetEstimatedArrivalDate(DateTime.Now.Date);
Then you can test it as follows:
DateTime actual = GetEstimatedArrivalDate(new DateTime(2010, 2, 10));
DateTime expected = ...;
// etc...
Note that this also fixes a potential bug in your program where the date changes between consecutive calls to DateTime.Now.
Make your class take an IClock parameter (via constructor or property)
interface IClock
{
DateTime Now { get; }
}
You can then use a fake implementation for testing
class FakeClock : IClock
{
DateTime Now { get; set }
}
and a real implementation the rest of the time.
class SystemClock : IClock
{
DateTime Now { get { return DateTime.Now; } }
}
You could pass in a delegate that returns DateTime.Now during normal execution, and then in your test pass in another delegate that returns a fixed date, and assert your result based on that.
I'll give the controversial answer, don't test it.
The logic is trivial and it has zero dependencies, i believe in good code coverage but not when it increases complexity for no real gain.
I would suggest doing this as Mark suggests, but with the addition of a overloaded call for production use that takes no parameter and uses DateTime.Now
private DateTime GetEstimatedArrivalDate()
{
return GetEstimatedArrivalDate(DateTime.Now);
}
private DateTime GetEstimatedArrivalDate(DateTime currentDate)
{
DateTime estimatedDate;
if (currentDate.DayOfWeek >= DayOfWeek.Thursday)
{
estimatedDate = currentDate.AddDays(6);
}
else
{
estimatedDate = currentDate.AddDays(5);
}
return estimatedDate;
}
Generally speaking, you'd want to abstract the method of obtaining the current date and time behind an interface, eg:
public interface IDateTimeProvider
{
DateTime Now { get; }
}
The real service would be:
public class DateTimeProvider: IDateTimeProvider
{
public DateTime Now
{
get
{
return DateTime.Now;
}
}
}
And a test service would be:
public class TestDateTimeProvider: IDateTimeProvider
{
private DateTime timeToProvide;
public TestDateTimeProvider(DateTime timeToProvide)
{
this.timeToProvide = timeToProvide;
}
public DateTime Now
{
get
{
return timeToProvide;
}
}
}
For services that require the current time, have them take an IDateTimeProvider as a dependency. For the real thing, pass a new DateTimeProvider(); when you're a component, pass in a new TestDateTimeProvider(timeToTestFor).