Skip to content

Instantly share code, notes, and snippets.

@CraftyFella
Last active June 16, 2023 02:50
Show Gist options
  • Save CraftyFella/42f459f7687b0b8b268fc311e6b4af08 to your computer and use it in GitHub Desktop.
Save CraftyFella/42f459f7687b0b8b268fc311e6b4af08 to your computer and use it in GitHub Desktop.
Static Clock.cs which allows overriding of time in tests (running in parallel) dotnet core friendly
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Example
{
public static class Clock
{
private static Func<DateTime> _utcNow = () => DateTime.UtcNow;
static AsyncLocal<Func<DateTime>> _override = new AsyncLocal<Func<DateTime>>();
public static DateTime UtcNow => (_override.Value ?? _utcNow)();
public static void Set(Func<DateTime> func)
{
_override.Value = func;
}
public static void Reset()
{
_override.Value = null;
}
}
}
@CraftyFella
Copy link
Author

CraftyFella commented Dec 1, 2017

Example usage:

            Clock.Set(() => new DateTime(2000, 1, 1));
            Console.WriteLine($"Time is now {Clock.UtcNow}");
            Console.WriteLine($"Time is reset");
            Clock.Reset();
            Console.WriteLine($"Time is now {Clock.UtcNow}");
            Console.ReadLine();```

output:

```Time is now 01/12/2017 18:01:05
Time is now 01/01/2000 00:00:00
Time is reset
Time is now 01/12/2017 18:01:05```

@CraftyFella
Copy link
Author

CraftyFella commented Dec 1, 2017

Tests written in xunit that proves the time's don't clash with each other:

    public class Class1
    {
        [Fact]
        public void Test1()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 1, 1));

            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 1, 1));

            Console.WriteLine("finished Test1");
        }

        [Fact]
        public void Test2()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 2, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 2, 1));
            Console.WriteLine("finished Test2");
        }

        [Fact]
        public void Test3()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 3, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 3, 1));
            Console.WriteLine("finished Test3");
        }
    }

    [Collection("Unique Collection to force parallel tests 2")]
    public class Class2
    {
        [Fact]
        public void Test4()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 4, 1));

            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 4, 1));

            Console.WriteLine("finished Test4");
        }

        [Fact]
        public void Test5()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 6, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 6, 1));
            Console.WriteLine("finished Test5");
        }

        [Fact]
        public void Test6()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 6, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 6, 1));
            Console.WriteLine("finished Test6");
        }
    }

    [Collection("Unique Collection to force parallel tests 3")]
    public class Class3
    {
        [Fact]
        public void Test7()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 7, 1));

            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 7, 1));

            Console.WriteLine("finished Test7");
        }

        [Fact]
        public void Test8()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 8, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 8, 1));
            Console.WriteLine("finished Test8");
        }

        [Fact]
        public void Test9()
        {
            Assert.Equal(DateTime.UtcNow.Date, Clock.UtcNow.Date);
            Clock.Set(() => new DateTime(2000, 9, 1));
            Task.Delay(2000).Wait();
            var time = Clock.UtcNow;

            Assert.Equal(time, new DateTime(2000, 9, 1));
            Console.WriteLine("finished Test9");
        }
    }

output:

finished Test7
finished Test6
finished Test2
finished Test4
finished Test9
finished Test1
finished Test5
finished Test8
finished Test3
  Finished:    MyFirstUnitTests
=== TEST EXECUTION SUMMARY ===
   Tests  Total: 9, Errors: 0, Failed: 0, Skipped: 0, Time: 6.144s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment