Wir schreiben Komponententests für asynchronen Code mit MSTest und Moq.Mocking Async Methoden
So haben wir einige Code, wie etwas aussieht:
var moq = new Mock<Foo>();
moq.Setup(m => m.GetAsync())
.Returns(Task.FromResult(10));
Oder wie diese auf Projekte, die eine neuere Version von Moq haben
var moq = new Mock<Foo>();
moq.Setup(m => m.GetAsync())
.ReturnsAsync(10);
am Moq Blick Umsetzung ReturnsAsync:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(this IReturns<TMock, Task<TResult>> mock, TResult value) where TMock : class
{
TaskCompletionSource<TResult> completionSource = new TaskCompletionSource<TResult>();
completionSource.SetResult(value);
return mock.Returns(completionSource.Task);
}
Beide Methoden scheinen unter der Haube gleich zu sein. Beide erstellen eine TaskCompletionSource
, rufen Sie SetResult
und senden Sie die Task
So weit so gut.
Aber kurz laufende async
Methoden sind optimiert, um synchron zu agieren. Dies scheint zu implizieren, dass TaskCompletionSource
immer synchron ist, was auch darauf hindeutet, dass die Kontextbehandlung und alle damit verbundenen Probleme, die auftreten könnten, niemals passieren würden.
Also, wenn wir hatten einige Code, der einige async
tabu der tat, wie awaits
Mischen Wait()
und Result
, dass diese Probleme würden in Unit-Tests nicht erkannt werden.
Wäre es von Vorteil, eine Erweiterungsmethode zu erstellen, die immer die Kontrolle liefert? Etwas wie:
In diesem Fall hätten wir eine Methode, die garantiert asynchron ausgeführt wird.
Der wahrgenommene Vorteil wäre die Erkennung von schlechtem asynchronem Code. Zum Beispiel könnte es während des Komponententests irgendein Deadlocking oder Schlucken von Ausnahmen erfassen.
Ich bin mir nicht 100% sicher, dass dies der Fall ist, also würde mich wirklich interessieren, was die Community zu sagen hat.
Ich würde sagen gehen für 'ReturnsYieldingAsync', aber noch mehr, um potentielle Deadlocks zu erleben, die Sie benötigen, um einen Synchronisationskontext in Ihren Testläufern zu installieren, etwas wie [' AsyncPump'] (http: // blogs. msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx). – Noseratio
Ich denke, Sie sollten versuchen, einen Testfall zu schreiben, der 1. wie erwartet funktioniert und 2. Sie können einen Testfall erstellen, der exakt dem Testfall von 1 folgt, aber niemals 'ReturnsYieldingAsync' aufruft und fehlschlägt. –
@Noseratio Nice finden Sie auf der 'AsyncPump'. Das Hauptproblem, auf das wir stoßen, besteht darin, dass der Test, in den hineingelaufen wird, darin besteht, dass der Synchronisationskontext des Testlaufers null ist. Austauschen der 'AsyncPump' scheint der Weg zu sein, wie hier gezeigt http: // stackoverflow.com/questions/14087257/how-to-add-Synchronisation-Kontext-zu-Async-Test-Methode – swestner