Вот что я сделал в этих ситуациях: создайте сервис, который принимает делегат и выполняет его (предоставьте это через простой интерфейс, введите, где вы вызываете вещи асинхронно).
В реальном сервисе он будет выполняться с BeginInvoke и, следовательно, асинхронно. Затем создайте версию службы для тестирования, которая вызывает делегат синхронно.
Вот пример:
public interface IActionRunner
{
void Run(Action action, AsyncCallback callback, object obj);
void Run<T>(Action<T> action, T arg, AsyncCallback callback, object obj);
void Run<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2, AsyncCallback callback, object obj);
void Run<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, AsyncCallback callback, object obj);
void Run<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, AsyncCallback callback, object obj);
}
Асинхронная реализация этого сервиса выглядит следующим образом:
public void Run<T>(Action<T> action, T arg, AsyncCallback callback, object obj)
{
action.BeginInvoke(arg, callback, obj);
}
Синхронная реализация этого сервиса выглядит так:
public void Run<T>(Action<T> action, T arg, AsyncCallback callback, object obj)
{
action(arg);
}
Когда вы проводите модульное тестирование, если вы используете что-то вроде RhinoMocks и контейнера AutoMocking, вы можете поменять их в Synchronous ActionRunner:
_mocks = new MockRepository();
_container = new AutoMockingContainer(_mocks);
_container.AddService(typeof(IActionRunner), new SyncActionRunner());
_container.Initialize();
ActionRunner не нуждается в проверке; это всего лишь тонкий шпон над вызовом метода.