Search code examples
mstestasync-ctpthread-sleep

Async CTP v3, MS Test and Thread.Sleep


I have a long running task method, using Sleep

public Task LongRunning() {
    return Task.Factory.StartNew(
        () => {
            Trace.TraceInformation("Start Sleep");

            Thread.Sleep(10000);

            Trace.TraceInformation("End Sleep");
        });
}

This is called by my test, and it works fine

[TestMethod]
public void SimpleContinueWith() {
    Trace.TraceInformation("Start");

    LongRunning()
        .ContinueWith(
            t => Trace.TraceInformation("End")
        ).Wait();
}

> QTAgent32.exe Information: 0 : Start
> QTAgent32.exe Information: 0 : Start Sleep
> QTAgent32.exe Information: 0 : End Sleep
> QTAgent32.exe Information: 0 : End

But using async/await the test falls straight through

[TestMethod]
public async void SimpleAwait() {
    Trace.TraceInformation("Start");

    await LongRunning();

    Trace.TraceInformation("End");
}

> QTAgent32.exe Information: 0 : Start
> QTAgent32.exe Information: 0 : Start Sleep

Why is that then?


Solution

  • MSTest cannot (currently) handle asynchronous tests. I'm not sure if Microsoft is going to add this for the final release. Update: VS11 Beta did add support for async unit tests; see below.

    You can unit test asynchronous methods by providing an async context yourself. There's some included in the Async CTP (Microsoft Visual Studio Async CTP\Samples\(C# Testing) Unit Testing\AsyncTestUtilities), or you can use one I wrote called AsyncContext.

    Using AsyncContext, your test can be written as:

    [TestMethod]
    public void SimpleAwait() {
      AsyncContext.Run(async () =>
      {
        Trace.TraceInformation("Start");
    
        await LongRunning();
    
        Trace.TraceInformation("End");
      });
    }
    

    Update, 2012-02-05: Another option is the new AsyncUnitTests library. Install that NuGet package, change your TestClass to AsyncTestClass, and your async unit tests can be written much more naturally:

    [TestMethod]
    public async void SimpleAwait() {
      Trace.TraceInformation("Start");
    
      await LongRunning();
    
      Trace.TraceInformation("End");
    }
    

    Update, 2012-06-06: If you update to VS2012 Beta, you can define asynchronous unit tests; they just have to return Task:

    [TestMethod]
    public async Task SimpleAwait() {
      Trace.TraceInformation("Start");
    
      await LongRunning();
    
      Trace.TraceInformation("End");
    }