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.