Task.Wait() блокирует средство запуска Xamarin.iOS NUnit

У меня есть класс с такими методами:

private Task Sleep()
{
    return Task.Delay(SleepDuration);
}

public async Task<User> Login(string username, string password)
{
    await Sleep();

    return new User { Id = 1, Username = username };
}

Обратите внимание, что во время моих тестов SleepDuration установлено на 0.

Если я вызову следующее в тесте проекта iOS NUnit:

myClass.Login("username", "password").Wait();

Пользовательский интерфейс тестировщика приостанавливается и никогда не завершается. Если я добавлю точки останова, код никогда не достигнет строки после await. Тот же тест отлично работает в стандартном средстве запуска NUnit в проекте .Net 4.5 Mono. Это также отлично работает в моем приложении, хотя я никогда не вызываю Wait и всегда использую async/await.

Любые идеи? Есть ли что-то еще, что я могу использовать вместо Task.Delay, чтобы предотвратить взаимоблокировку? Я уже пробовал Task.Factory.StartNew(() => { }).


person jonathanpeppers    schedule 29.09.2013    source источник


Ответы (1)


Современные версии NUnit предоставляют SynchronizationContext для своих модульных тестов, чтобы они могли поддерживать модульные тесты async void.

Вполне вероятно, что этот контекст вызывает взаимоблокировку, когда вы блокируете асинхронный код (например, Wait). У меня есть запись в блоге, в которой подробно описывается взаимодействие. Обратите внимание, что эта взаимоблокировка происходит только в том случае, если Task.Delay возвращает еще не завершенное Task; для очень коротких задержек существует условие гонки, независимо от того, завершена ли Task к тому времени, когда она достигает Wait.

Я рекомендую вам использовать await в модульном тесте и сделать тестовый метод async Task.

person Stephen Cleary    schedule 29.09.2013
comment
Я использую шаблон проекта NUnit для Xamarin.iOS, он использует версию NUnit Lite (через MonoTouch.NUnitLite) и не поддерживает асинхронные тесты. Он отлично работает в обычном проекте NUnit Mono/.Net 4.5 даже с NUnit 2.6.0. Но я думаю, что 2.6.2 требуется для асинхронных тестов. - person jonathanpeppers; 30.09.2013
comment
Хорошо, ваш комментарий к незавершенной задаче привел меня к обходному пути. Я использовал Task.FromResult(true) вместо Task.Delay(0), но я все еще думаю, что это ошибка в версии NUnit для Xamarin.iOS, поскольку в стандартном проекте Mono NUnit все работает нормально. - person jonathanpeppers; 30.09.2013
comment
@jonathanpeppers XI 7.0 поставляется с NUnitlite 0.9, который поддерживает асинхронные тесты. - person poupou; 02.10.2013
comment
Я попробую асинхронный тест и дам вам знать. - person jonathanpeppers; 03.10.2013
comment
Async работает в iOS, но не в средстве запуска NUnit в Xamarin Studio. Мы как бы хотим, чтобы оба работали. Если я использую async/await, он работает на iOS, а вызов Wait() на Task работает в проекте Mono. Вызов Wait() также хорошо работает в MsTest в Visual Studio, что я всегда и делал. - person jonathanpeppers; 05.10.2013