Warum können Unit-Tests mit „asynchroner Leere“ nicht erkannt werden?

79

async void Unit-Tests können in Visual Studio 2012 nicht ausgeführt werden:

[TestClass]
public class MyTestClass
{
    [TestMethod]
    public async void InvisibleMyTestMethod()
    {
        await Task.Delay(1000);
        Assert.IsTrue(true);
    }
}

Wenn ich einen asynchronen Komponententest durchführen möchte, muss die Testmethode eine Aufgabe zurückgeben:

[TestMethod]
public async Task VisibleMyTestMethod()
{
    await Task.Delay(1000);
    Assert.IsTrue(true);
}

Wieso ist es so? Nicht dass ich unbedingt eine async voidTestmethode brauche , ich bin nur neugierig. Visual Studio 2012 gibt keine Warnung oder Fehler aus, wenn Sie eine async voidTestmethode erstellen , obwohl diese nicht ausgeführt werden kann ...

Max
quelle

Antworten:

83

async voidMethoden sollten als "Feuer und Vergessen" betrachtet werden - es gibt keine Möglichkeit zu warten, bis sie fertig sind. Wenn Visual Studio einen dieser Tests starten würde, könnte es nicht warten, bis der Test abgeschlossen ist (als erfolgreich markieren) oder Ausnahmen auslösen.

Mit a async Taskkann der Aufrufer warten, bis die Ausführung abgeschlossen ist, und alle Ausnahmen abfangen, die während der Ausführung ausgelöst werden.

Sehen Sie diese Antwort für mehr Diskussion async voidvs async Task.

Richard
quelle
3
Das ist nicht wahr. NUnit unterstützt async voidTests und wie und warum es unterstützt wird, wird in diesem Link ausführlich beschrieben . Siehe Antwort unten.
Anupam
21

Dies liegt nur daran, dass MSTest keine Komponententests unterstützt async void. Dies ist möglich , indem ein Kontext eingeführt wird, in dem sie ausgeführt werden können.

MSTest unterstützt dies nicht, wahrscheinlich weil Microsoft entschieden hat, dass es sich um eine zu große Änderung für vorhandene Tests handelt (es ist möglich, dass vorhandene Tests blockieren, wenn ihnen ein unerwarteter Kontext zugewiesen wird).

Es gibt keine Compiler-Warnung / Fehler, da es sich um einen vollkommen gültigen C # -Code handelt. Der einzige Grund, warum es nicht funktioniert, ist das Unit-Test-Framework (dh ich glaube, dass xUnit async voidTests unterstützt), und es wäre eine grobe Verletzung der Trennung von Bedenken, wenn der C # -Compiler Ihre Attribute überprüft und Sie bestimmt verwenden MSTest und entscheiden, dass Sie wirklich nicht verwenden wollten async void.

Stephen Cleary
quelle
1
In der ersten Implementierung (Visual Studio Preview) würde der Test erkannt und "ausgeführt". Das Problem war, dass die Methode beim ersten Warten enden würde und das war das Ergebnis des Tests.
Paulo Morgado
20

Ich habe in VS2015 festgestellt, dass mit Async dekorierte Testmethoden im Test Explorer nicht angezeigt werden. Am Ende entfernte ich das asynchrone Schlüsselwort und ersetzte den erwarteten Aufruf im Test durch eine task.Wait () und machte meine Aussagen zu task.Result.

Scheint in Ordnung zu sein. Ich habe es noch nicht mit Ausnahmetests versucht.

var task = TheMethodIWantToTestAsync(someValue);
task.Wait();
var response = task.Result;

Assert.IsNotNull(response);
Assert.IsTrue(response.somevalue);
Nick Wright
quelle
3
Denken Sie nicht, dass task.Wait () als aufrufende Task aufgerufen werden muss. Das Ergebnis ruft task.Wait () automatisch auf, wenn die Task noch nicht abgeschlossen ist.
stt106