Почему нельзя распознать модульные тесты async void?

79

async void модульные тесты нельзя запускать в Visual Studio 2012:

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

Если я хочу иметь асинхронный модульный тест, метод теста должен возвращать Task:

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

Почему это так? Не то чтобы мне абсолютно необходим async voidметод тестирования, мне просто любопытно. Visual Studio 2012 не выдает ни предупреждений, ни ошибок при создании async voidметода тестирования, даже если он не может быть запущен ...

Максимум
источник

Ответы:

83

async voidметоды следует рассматривать как «выстрелил и забыл» - дождаться их завершения нельзя. Если бы Visual Studio запустила один из этих тестов, она не смогла бы дождаться завершения теста (пометить его как успешный) или перехватить возникшие исключения.

С помощью async Taskвызывающий может дождаться завершения выполнения и перехватывать любые исключения, возникающие во время его выполнения.

Смотрите этот ответ для более детального обсуждения async voidпротив async Task.

Ричард
источник
3
Это неправда. NUnit поддерживает async voidтесты, и в этой ссылке в некоторой степени подробно описано, как и почему это нужно поддерживать . См. Ответ ниже.
Анупам,
21

Просто потому, что MSTest не поддерживает async voidмодульные тесты. Это можно сделать, введя контекст, в котором они могут выполняться.

MSTest не поддерживает это, вероятно, потому, что Microsoft решила, что это слишком много изменений для существующих тестов (возможно, существующие тесты зашли бы в тупик, если бы им дали неожиданный контекст).

Предупреждения / ошибки компилятора нет, потому что это совершенно правильный код C #. Единственная причина, по которой это не работает, - это структура модульного тестирования (т. Е. Я считаю, что xUnit поддерживает async voidтесты), и для компилятора C # было бы грубым нарушением разделения задач, если бы он посмотрел на ваши атрибуты и определил вас. используете MSTest и решили, что вы действительно не хотите его использовать async void.

Стивен Клири
источник
1
В первой реализации (предварительная версия Visual Studio) тест будет распознан и «запущен». Проблема заключалась в том, что метод завершался при первом ожидании, и это было результатом теста.
Пауло Моргадо,
21

В VS2015 я обнаружил, что любые методы тестирования, оформленные с помощью async, не отображаются в обозревателе тестов. В итоге я удалил ключевое слово async и заменил вызов await в тесте на task.Wait () и выполнил свои утверждения для task.Result.

Кажется, работает нормально. Еще не пробовал с тестированием исключений.

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

Assert.IsNotNull(response);
Assert.IsTrue(response.somevalue);
Ник Райт
источник
3
Не думайте, что ему нужно вызывать task.Wait (), поскольку вызов task.Result вызовет task.Wait () автоматически, если задача не завершена.
stt106,