¿Por qué no se pueden reconocer las pruebas unitarias "async void"?

79

async void las pruebas unitarias no se pueden ejecutar en Visual Studio 2012:

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

Si quiero tener una prueba unitaria asincrónica, el método de prueba debe devolver una Tarea:

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

¿Por que es esto entonces? No es que necesite absolutamente un async voidmétodo de prueba, solo tengo curiosidad. Visual Studio 2012 no da advertencias ni errores cuando crea un async voidmétodo de prueba aunque no se pueda ejecutar ...

Max
fuente

Respuestas:

83

async voidLos métodos deben considerarse como "Disparar y olvidar"; no hay forma de esperar a que terminen. Si Visual Studio iniciara una de estas pruebas, no podría esperar a que se complete la prueba (marcarla como exitosa) o capturar las excepciones que surjan.

Con un async Task, la persona que llama puede esperar a que se complete la ejecución y capturar cualquier excepción generada mientras se ejecuta.

Ver esta respuesta para más discusión de async voidfrente async Task.

Ricardo
fuente
3
Esto no es verdad. NUnit admite async voidpruebas y cómo y por qué apoyarlas se detalla hasta cierto punto en este enlace . Vea la respuesta a continuación.
Anupam
21

Es solo porque MSTest no admite async voidpruebas unitarias. Es posible hacerlo introduciendo un contexto en el que se puedan ejecutar.

MSTest no admite esto, probablemente porque Microsoft decidió que era un cambio demasiado grande para las pruebas existentes (es posible que las pruebas existentes se bloqueen si se les diera un contexto inesperado).

No hay advertencia / error del compilador porque es un código C # perfectamente válido. La única razón por la que no funciona es debido al marco de prueba unitario (es decir, creo que xUnit sí admite async voidpruebas), y sería una grave violación de la separación de preocupaciones que el compilador de C # mire sus atributos, lo determine está usando MSTest y decide que realmente no desea usar async void.

Stephen Cleary
fuente
1
En la primera implementación (Vista previa de Visual Studio), la prueba se reconocería y se "ejecutaría". El problema era que el método terminaría en la primera espera y ese fue el resultado de la prueba.
Paulo Morgado
21

Encontré en VS2015 que cualquier método de prueba decorado con async no se mostraría en el Explorador de pruebas. Terminé eliminando la palabra clave async y reemplazando la llamada en espera en la prueba con una tarea.Espere () y realicé mis asertiones en task.Result.

Parece estar funcionando bien. Todavía no lo he probado con pruebas de excepción.

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

Assert.IsNotNull(response);
Assert.IsTrue(response.somevalue);
Nick Wright
fuente
3
No crea que necesita llamar a task.Wait () como llamando a task.Result llamará a task.Wait () automáticamente si la tarea no ha terminado.
stt106