Here is an old pattern I used to use in C# whenever I wanted to freeze time in a test, and then verify that something happened after.

You define a Clock object where you can freeze and set the time. Then whenever you want a time in your system or in tests you simply ask it for it’s time.

DateTime now = Clock.CurrentTime();

Or in a test you can do something like this.

  [Fact]
        public void When_updating_a_user()
        {
            using(Clock.Freeze())
            {
                // Add user at this time
                DateTime currentTime = Clock.CurrentTime();
                fixture.Add(randomUserName);

                // Update user 5 minutes later
                Clock.Add(new TimeSpan(0, 5, 0));
                DateTime newCurrentTime = Clock.CurrentTime();
                repository.UpdateUser(new User(randomUserName, true));

                User user = repository.FindBy(randomUserName);
                Assert.Equal(principalUserName, user.CreatedBy);
                Assert.Equal(currentTime, user.CreatedDate);
                Assert.Equal(principalUserName, user.ModifiedBy);
                Assert.Equal(newCurrentTime, user.ModifiedDate);
            }
        }

Clock

using System;

namespace src.utils
{
    public class Clock
    {
        private static bool timeFrozen;
        private static DateTime currentTime;

        public static UnFreezeClock Freeze()
        {
            DateTime now = DateTime.Now;
            return Freeze(new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second));
        }

        public static UnFreezeClock Freeze(DateTime time)
        {
            timeFrozen = true;
            currentTime = time;

            return new UnFreezeClock();
        }

        public static DateTime CurrentTime()
        {
            if (timeFrozen)
                return currentTime;
            else
                return DateTime.Now;
        }

        public static void Add(TimeSpan timeSpan)
        {
            if (timeFrozen)
                currentTime = currentTime.Add(timeSpan);
        }

        public static void Unfreeze()
        {
            timeFrozen = false;
            currentTime = DateTime.Now;
        }
    }
}
Advertisements