Skip to content

Simulates passage of time to test asynchronous long-running .NET code in synchronous way

License

Notifications You must be signed in to change notification settings

Tolyandre/fake-async

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fake-async C#

test workflow

Simulates passage of time to test asynchronous long-running code in synchronous way.

This library is inspired from Angular's FakeAsync.

bool flag = false;

async Task MethodUnderTest()
{
    await Task.Delay(TimeSpan.FromSeconds(10));

    flag = true;

    _ = Task.Run(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(10));

        Console.WriteLine("Hello from faked thread pool");
    });
}

var fakeAsync = new FakeAsync
{
    UtcNow = new DateTime(2020, 10, 20),
};
          
fakeAsync.Isolate(async () =>
{
    var testing = MethodUnderTest();

    // Current time is changed
    Console.WriteLine("{0}, flag={1}", DateTime.UtcNow, flag); // 2020-10-20 00:00:00, false

    // Skip 9s synchronously, no real delay
    fakeAsync.Tick(TimeSpan.FromSeconds(9));

    Console.WriteLine("{0}, flag={1}", DateTime.UtcNow, flag); // 2020-10-20 00:00:09, false

    // Skip 1s more
    fakeAsync.Tick(TimeSpan.FromSeconds(1));

    // Flag changed
    Console.WriteLine("{0}, flag={1}", DateTime.UtcNow, flag); // 2020-10-20 00:00:10, true

    // Now MethodUnderTest() is completed, await it to propagate any exceptions
    await testing;

    // Skip remaining time to display the message
    fakeAsync.Tick(TimeSpan.FromSeconds(10)); // Hello from faked thread pool
});

// Print real system time
Console.WriteLine(DateTime.UtcNow);

Supported calls:

  • DateTime.Now
  • DateTime.UtcNow
  • Task.Run()
  • Task.Factory.StartNew() when TaskScheduler is ThreadPoolTaskScheduler (default)
  • new Task().Start()
  • Task.Delay()
  • Thread.Sleep() (TODO)
  • Task.Yield()

Stopwatch is not changed, so it is possible to measure time.

Known issues

Tiered compilation in .NET Core 3.0 is enabled by default. It occasionally overrides FakeAsync patches, so mock is not reliable. Currently, there is an open issue in Harmony.Lib. Workaround is to disable tiered compilation in tests project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TieredCompilation>false</TieredCompilation>
  </PropertyGroup>

</Project>

After changing this setting Clean and Rebuild solution to take effect.

Road map

  • Suitable API to test asynchronous long running code
  • Implement tick() (like Angular's FakeAsync)
  • Allow tests with Polly timeout policies
  • Make a Nuget package

Credits

  • Harmony - a library for patching, replacing and decorating .NET and Mono methods during runtime

About

Simulates passage of time to test asynchronous long-running .NET code in synchronous way

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages