Unit Testing: DateTime.Now

I have some unit tests that expects the 'current time' to be different than DateTime.Now and I don't want to change the computer's time, obviously. What's the best strategy to achieve this?

Thanks

-------------Problems Reply------------

The best strategy is to wrap the current time in an abstraction and inject that abstraction into the consumer.

Alternatively, you can also define a time abstraction as an Ambient Context:

public abstract class TimeProvider
{
private static TimeProvider current =
DefaultTimeProvider.Instance;

public static TimeProvider Current
{
get { return TimeProvider.current; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
TimeProvider.current = value;
}
}

public abstract DateTime UtcNow { get; }

public static void ResetToDefault()
{
TimeProvider.current = DefaultTimeProvider.Instance;
}
}

This will enable you to consume it like this:

var now = TimeProvider.Current.UtcNow;

In a unit test, you can replace TimeProvider.Current with a Test Double/Mock object. Example using Moq:

var timeMock = new Mock<TimeProvider>();
timeMock.SetupGet(tp => tp.UtcNow).Returns(new DateTime(2010, 3, 11));
TimeProvider.Current = timeMock.Object;

However, when unit testing with static state, always remember to tear down your fixture by calling TimeProvider.ResetToDefault().

Moles:

[Test]
public void TestOfDateTime()
{
var firstValue = DateTime.Now;
MDateTime.NowGet = () => new DateTime(2000,1,1);
var secondValue = DateTime.Now;
Assert(firstValue > secondValue); // would be false if 'moleing' failed
}

Disclaimer - I work on Moles

These are all good answers, this is what I did on a different project:

Usage:

Get Today's REAL date Time

var today = SystemTime.Now().Date;

Instead of using DateTime.Now, you need to use SystemTime.Now()... It's not hard change but this solution might not be ideal for all projects.

Time Traveling (Lets go 5 years in the future)

SystemTime.SetDateTime(today.AddYears(5));

Get Our Fake "today" (will be 5 years from 'today')

var fakeToday = SystemTime.Now().Date;

Reset the date

SystemTime.ResetDateTime();

/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public static class SystemTime
{
/// <summary> Normally this is a pass-through to DateTime.Now, but it can be overridden with SetDateTime( .. ) for testing or debugging.
/// </summary>
public static Func<DateTime> Now = () => DateTime.Now;

/// <summary> Set time to return when SystemTime.Now() is called.
/// </summary>
public static void SetDateTime(DateTime dateTimeNow)
{
Now = () => dateTimeNow;
}

/// <summary> Resets SystemTime.Now() to return DateTime.Now.
/// </summary>
public static void ResetDateTime()
{
Now = () => DateTime.Now;
}
}

You have some options for doing it:

  1. Use mocking framework and use a DateTimeService (Implement a small wrapper class and inject it to production code). The wrapper implementation will access DateTime and in the tests you'll be able to mock the wrapper class.
  2. Use Typemock Isolator, it can fake DateTime.Now and won't require you to change the code under test.
  3. Use Moles, it can also fake DateTime.Now and won't require change in production code.

Some examples:

Wrapper class using Moq:

[Test]
public void TestOfDateTime()
{
var mock = new Mock<IDateTime>();
mock.Setup(fake => fake.Now)
.Returns(new DateTime(2000, 1, 1));

var result = new UnderTest(mock.Object).CalculateSomethingBasedOnDate();
}

public class DateTimeWrapper : IDateTime
{
public DateTime Now { get { return DateTime.Now; } }
}

Faking DateTime directly using Isolator:

[Test]
public void TestOfDateTime()
{
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2000, 1, 1));

var result = new UnderTest().CalculateSomethingBasedOnDate();
}

Disclaimer - I work at Typemock

Mock Objects.

A mock DateTime that returns a Now that's appropriate for your test.

One special note on mocking DateTime.Now with TypeMock...

The value of DateTime.Now must be placed into a variable for this to be mocked properly. For example:

This does not work:

if ((DateTime.Now - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))

However, this does:

var currentDateTime = DateTime.Now;
if ((currentDateTime - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))

I ran into this same issue but found a research project from Microsoft that solves this issue.

http://research.microsoft.com/en-us/projects/moles/

Moles is a lightweight framework for test stubs and detours in .NET that is based on delegates. Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types

// Let's detour DateTime.Now
MDateTime.NowGet = () => new DateTime(2000,1, 1);

if (DateTime.Now == new DateTime(2000, 1, 1);
{
throw new Exception("Wahoo we did it!");
}

The sample code was modified from the original.

I had done what other suggested and abstracted the DateTime into a provider. It just felt wrong and I felt like it was too much just for testing. I'm going to implement this into my personal project this evening.

Add a fake assembly for System (right click on System reference=>Add fake assembly).

And write into your test method:

using (ShimsContext.Create()) { System.Fakes.ShimDateTime.NowGet = () => new DateTime(2014, 3, 10); MethodThatUsesDateTimeNow(); }

Category:c# Views:1 Time:2010-03-11

Related post

  • Are there any languages that allow units? 2009-08-21

    When writing the following today in C# DateTime.Now.AddYears(-60) I wondered whether there are any languages that allow a more natural syntax with units: DateTime.Now - 60years Does anyone know of any? Specifically, I'm interested in the presence of

  • SQL View displaying current status of a "unit" for every date that something changes with the "unit" 2010-03-03

    In a project I'm working on, there is a table of units and then there are several tables that pertain to the units' locations at a given point in time as well as other factors for a given point in time. For example, Unit1 might be at LocationA on 1/1

  • c# datetime timespan duration? 2011-02-24

    I have a log of in and out times. I want to have a column in the log be the total time during one login and next to that the total login times for that person for the entire log. I've been getting the first duration using the TimeSpan object, but to

  • Getting a Weighted Average Date Value? 2011-06-24

    If I have 50% weight on 6/3/2011 and 50% weight on 6/1/2011, the weighted average will be 6/2/2011. Now, I can't seem to figure out how I can do this with uneven weights, since it's not like you can multiply a DateTime by a double, and sum up the res

  • How can I round up the time to the nearest X minutes? 2011-08-11

    Is there a simple function for rounding UP a DateTime to the nearest 15 minutes? E.g. 2011-08-11 16:59 becomes 2011-08-11 17:00 2011-08-11 17:00 stays as 2011-08-11 17:00 2011-08-11 17:01 becomes 2011-08-11 17:15 --------------Solutions-------------

  • Should I Write Tests for Argument Exceptions? 2011-09-02

    When applying TDD, do you create tests that verify expected exceptions for arguments (ArgumentException, ArgumentNullException, InvalidOperation, etc.) or just ones that are "known", for example, CustomerDelinquentException ? What about equals, getha

  • JavaScript function not running (console returns that the function "is not a function") 2012-03-16

    I created a .aspx web page for SharePoint 2010 that uses JQuery to extract list item data from a SharePoint list and then uses that data to populate a Simile Timeline. The page includes a filter, which I believe uses some form of AJAX, updates/filter

  • DateTime Problem in Rails Unit Tests 2009-12-21

    I'm working on unit tests for my Rails app and have run into the following problem. I have an Event model with a fixture that boils down to: concert: name: Wallflowers start_at: <%= DateTime.new(1999) %> In my unit test, I have the following as

  • How to set DateTime as ValuesAttribute to unit test? 2010-12-03

    I want to do something like this [Test] public void Test([Values(new DateTime(2010, 12, 01), new DateTime(2010, 12, 03))] DateTime from, [Values(new DateTime(2010, 12, 02), new DateTime(2010, 12, 04))] DateTime to) { IList<MyObject> result = My

  • Strategies for dealing with DateTime.Now in unit tests 2011-01-04

    I have business logic that does not perform certain functions on Saturday or Sunday. I want my unit tests to verify that these functions are performed, but the tests will fail on Saturday/Sunday. I figure the easiest route is to have the unit tests c

  • Unit testing and DateTime behaviour explanation needed 2012-03-26

    unit test: test "job update date" do @job.save @job.company = 'New Company' now = DateTime.now @job.save assert_equal @job.updated_at, now end I end up with: 1) Failure: test_job_update_date(JobTest) [test/unit/job_test.rb:32]: <Mon, 26 Mar 2012 1

  • How to mock DateTime.Now in unit tests? 2012-03-30

    The normal solution is to hide it behind interface. public class RecordService { private readonly ISystemTime systemTime; public RecordService(ISystemTime systemTime) { this.systemTime = systemTime; } public void RouteRecord(Record record) { if (reco

  • Why does this unit test fail when testing DateTime equality? 2008-12-12

    Using NUnit 2.2 on .NET 3.5, the following test fails when using DateTime.Equals. Why? [TestFixture] public class AttributeValueModelTest { public class HasDate { public DateTime? DateValue { get { DateTime value; return DateTime.TryParse(ObjectValue

  • Is there any easy way to increment a DateTime by monthly/yearly/daily units without having to parse it out like crazy? 2009-09-30

    I need to set up billing cycles and process payments. So for example I will process a payment immediately and then set the next one up to process exactly one month from then. So if I get DateTime.Now is there any quick way to just add a month to it?

  • Is DateTime.Now the best way to measure a function's performance? 2008-08-26

    I need to find a bottleneck and need to accurately as possible measure time. Is the following code snippet the best way to measure the performance? DateTime startTime = DateTime.Now; // Some execution process DateTime endTime = DateTime.Now; TimeSpan

  • What's a good way to overwrite DateTime.Now during testing? 2008-09-04

    I've got some (C#) code that relies on today's date to correctly calculate things in the future. If I use today's date in the testing, I have to repeat the calculation in the test, which doesn't feel right. What's the best way to set the date to a kn

  • How to check if one DateTime is later than another in C# 2008-09-18

    I have two DateTime objects: StartDate and EndDate. I want to make sure StartDate is before EndDate. How is this done in C#? --------------Solutions------------- if (StartDate < EndDate) // code if you just want the dates, and not the time if (Sta

  • Is conditional compilation a valid mock/stub strategy for unit testing? 2008-09-18

    In a recent question on stubbing, many answers suggested C# interfaces or delegates for implementing stubs, but one answer suggested using conditional compilation, retaining static binding in the production code. This answer was modded -2 at the time

  • Creating a DateTime in a specific Time Zone in c# fx 3.5 2008-10-29

    I'm trying to create a unit test to test the case for when the timezone changes on a machine because it has been incorrectly set and then corrected. In the test I need to be able to create DateTime objects in a none local time zone to ensure that peo

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.155 (s). 11 q(s)