Модульное тестирование методов async void (выстрелил и забыл)C#

Место общения программистов C#
Anonymous
Модульное тестирование методов async void (выстрелил и забыл)

Сообщение Anonymous »

Я пишу тесты в MSTest для приложения WPF, которое содержит вызовы асинхронных методов void (шаблон «выстрелил и забыл»).
Моя цель — синхронно запускать этот код во время тестов.
Возможно ли это?
Я пробовал с «синхронным» SynchronizationContext:

Код: Выделить всё

public class SynchronousSynchronizationContext : SynchronizationContext
{
private readonly ConcurrentQueue _workItems = new ConcurrentQueue();
private readonly AutoResetEvent _workItemsAvailable = new AutoResetEvent(false);

public override void Post(SendOrPostCallback d, object state)
{
Trace.WriteLine("SynchronousSynchronizationContext.Post(), start");

// Execute the callback immediately
d(state);

Trace.WriteLine("SynchronousSynchronizationContext.Post(), end");
}

/* enqueues the work item to be completed later:
public override void Post(SendOrPostCallback d, object state)
{
Trace.WriteLine("SynchronousSynchronizationContext.Post()");

_workItems.Enqueue((d, state));
_workItemsAvailable.Set();
}
*/

public override void Send(SendOrPostCallback d, object state)
{
Trace.WriteLine("SynchronousSynchronizationContext.Send()");

d(state);
}

public void Run()
{
Trace.WriteLine("SynchronousSynchronizationContext.Run()");

while (_workItems.TryDequeue(out var workItem))
{
workItem.Item1(workItem.Item2);
}
}

public void Complete()
{
Trace.WriteLine("SynchronousSynchronizationContext.Complete()");

while (_workItems.TryDequeue(out var workItem))
{
Trace.WriteLine("SynchronousSynchronizationContext, execute callback");

// execute callback.
// The workItem is a tuple where Item1 is the callback and Item2 is the state object.
workItem.Item1(workItem.Item2);
}
}
}
Но это не работает. Метод Post() не запускает обратный вызов синхронно, как мне хотелось бы.
Вместо этого мне приходится явно вызывать Complete() в различных точках моего тестового метода:

Код: Выделить всё

private SynchronousSynchronizationContext _syncContext;

[TestInitialize]
public void TestInitialize()
{
_syncContext = new SynchronousSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(_syncContext);
}

[TestMethod]
public void MyTest_ReturnsData()
{
// ACT
MyTest();

// Finish all fire-and-forget tasks:
_syncContext.Complete();

// ASSERT
...

}
Есть ли способ синхронно запустить код без вызова Complete()?

Вернуться в «C#»