Some modern unit testing libraries (e.g., xUnit) already include single-threaded SynchronizationContext instances by default. Others do not (e.g., MSTest).
My AsyncEx library has an AsyncContext that installs a single-threaded SynchronizationContext and just processes the queue of messages on that single thread. Usage is quite simple:
public Task MyTestMethod() => AsyncContext.Run(async () =>
{
// asynchronous code here.
});
AsyncContext was designed for unit tests and Console applications, and has proper handling of some more exotic scenarios, e.g.:
async void methods are detected and the Run method will not return until they are complete.
AsyncContext.Run allows returning a result value, useful if you want to do your assertions outside of the asynchronous code.
- If the delegate passed to
Run propagates an exception or if any exception is propagated out of an async void method, then that exception propagates out of AsyncContext.Run (without exception wrappers and preserving the exception call stack).
However, AsyncContext is just a SynchronizationContext (with a "runner"), and has no notion of UI-specific thread synchronization mechanisms (e.g., Dispatcher, Control.Invoke). If you need to test code that uses a dispatcher or control, then you'll need to use WpfContext or WindowsFormsContext, which were helper types from the original Async CTP.