How to check the logic, which depends on the current date

I have this method, which depends on the current date. He checks if today is Sun, Mon, Tue or Wed, then he gives 5 days time for the arrival of the goods sent. If his Thur, Fri or Sat, then he gives 6 days of time to account for the weekend.

private DateTime GetEstimatedArrivalDate() { DateTime estimatedDate; if (DateTime.Now.DayOfWeek >= DayOfWeek.Thursday) { estimatedDate = DateTime.Now.Date.AddDays(6); } else { estimatedDate = DateTime.Now.Date.AddDays(5); } return estimatedDate; } 

The logic of actual evaluation is more complex. I simplified this for this question. My question is how to write unit test for something like this, which depends on today's date?

+7
c # unit-testing
source share
8 answers

You need to pass the current date 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 check it as follows:

 DateTime actual = GetEstimatedArrivalDate(new DateTime(2010, 2, 10)); DateTime expected = ...; // etc... 

Note that this also fixes a potential error in your program where the date changes between successive calls to DateTime.Now .

+17
source share

Generally speaking, you want to distract the method of getting the current date and time of the interface, for example:

 public interface IDateTimeProvider { DateTime Now { get; } } 

The real service will be:

 public class DateTimeProvider: IDateTimeProvider { public DateTime Now { get { return DateTime.Now; } } } 

And the test service will 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 current time, ask them to take IDateTimeProvider as a dependency. For real, pass the new DateTimeProvider (); when you are a component, go to the new TestDateTimeProvider (timeToTestFor).

+9
source share

Make your class using the IClock parameter (via constructor or property)

 interface IClock { DateTime Now { get; } } 

Then you can use a fake implementation for testing

 class FakeClock : IClock { DateTime Now { get; set } } 

and real implementation the rest of the time.

 class SystemClock : IClock { DateTime Now { get { return DateTime.Now; } } } 
+2
source share

I will give a controversial answer, do not check it.

The logic is trivial and has zero dependencies, I believe in good code coverage, but not when it increases complexity without real gain.

+1
source share

It seems that there are a fairly limited number of cases in which you can test them each explicitly. The method depends on today's date, but the output depends only on the day of the week, and each date has a day of the week.

0
source share

You can 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 approves your result based on that.

0
source share

One “general” way to do this is to “fake” the current system date (which can be done in several ways), and then check your code for “known” dates.

Another interesting way is to slightly modify your implementation:

 private DateTime GetEstimatedArrivalDate() { return GetEstimatedArrivalDate(DateTime.Now); } private DateTime GetEstimatedArrivalDate(DateTime forDate) { DateTime estimatedDate; if (forDate.DayOfWeek >= DayOfWeek.Thursday) { estimatedDate = forDate.Date.AddDays(6); } else { estimatedDate = forDate.Date.AddDays(5); } return estimatedDate; } 

And then use the method with a parameter to check for "immediate" dates.

0
source share

I suggest doing it like Mark , but with the addition of an overloaded call for production use, which does not accept a 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; } 
0
source share

All Articles