Как обсуждалось в # 268, класс GuardClauseAssertion
не ожидает завершения задач, что делает его неспособным проверять быстрые методы без
Это вполне понятно, ведь отказоустойчивый режим - действительно лучший вариант. Тем не менее, кажется невозможным реализовать быстрое отказоустойчивое поведение при работе с методами, отмеченными ключевым словом async
.
кажется невозможным реализовать поведение _fail fast_ при работе с методами, отмеченными ключевым словом
async
.
Как так? Вы можете привести пример?
@ploeh В принципе, _any_ async
метод не работает без сбоев. Рассмотрим следующий пример:
`` С #
общедоступная асинхронная задача
{
if (arg == null) выбросить новое исключение ArgumentNullException (nameof (arg));
await Task.Yield();
return default;
}
`` ''
Этот метод не срабатывает, если вы вызываете его, будет null
. Вместо этого возвращается неудачный Task
. Следовательно, GuardClauseAssertion в его текущей форме не работает и жалуется на отсутствие защитного предложения.
В реальном приложении почти весь код - async
, поэтому каждый вызов - awaited
и немедленно выдается исключение. Так что совершенно нормально, что принцип «быстрого отказа» нарушается в том случае, если вы должны await
Task, чтобы увидеть исключение.
Конечно, вы можете как-то переписать код, чтобы он сразу же вышел из строя (создайте приватную функцию с ключевым словом async
и переместите туда всю логику), но это не имеет практического смысла.
В реальном приложении почти весь код -
async
, поэтому каждый вызов -awaited
и сразу же выдается исключение.
Это справедливый момент; Я принимаю этот аргумент.
Иногда я отвлекаюсь, когда кто-то утверждает или подразумевает (с небольшими доказательствами), что что-то _невозможно _...
Иногда я отвлекаюсь, когда кто-то утверждает или подразумевает (с небольшими доказательствами), что что-то невозможно ...
Да, это справедливо
Теперь позвольте мне подумать, как я могу переделать GuardClauseAssertion
чтобы не было логического флага - если честно, мне это тоже не нравится. Увидимся позже в PR.
Теперь позвольте мне подумать, как я могу перепроектировать
GuardClauseAssertion
чтобы не было логического флага
Я бы подумал, что, как предположил @moodmosaic , новый класс мог бы быть лучшим дизайном. Я не особо разбирался в проблеме, поэтому оставляю за собой право ошибаться 😄
Вот решение, которое я использовал.
async
сигнатуры метода.async
Пример:
public Task<int> GetNumberAsync(MyObject obj)
{
// Fail-fast behavior
if (request is null)
throw new ArgumentNullException(nameof(obj));
async Task<int> work()
{
var items = await obj.GetItemsAsync(); // whatever you need to call
return items.Count();
}
return work();
}
Для меня это было хорошим решением. Спасибо за вашу помощь.
@mniak Интересно есть пример того , что конкретный @zvirja предложил здесь .
Лично мне это не очень нравится, потому что мы загрязняем этот метод «уловками» в пользу среды тестирования, что для меня очень плохо пахнет, и я бы не хотел, чтобы моя команда использовала этот шаблон.
Оставьте его открытым, чтобы реализовать поддержку естественным образом. Когда-нибудь. В ближайшем будущем. Или всего один день.
Привет. Мы наткнулись именно на эту проблему и были удивлены, что пока не существует хорошего решения.
Есть ли причины не реализовывать для этого новый класс?
Я не знаю внутренних деталей AutoFixture, но если бы у нас был MethodInfo, доступный в классе GuardClauseAssertion для Method-to-Test, мы могли бы взглянуть на его CustomAttributes и определить, является ли он методом Async или нет (https: / /stackoverflow.com/a/20350646). Так что, возможно, переключатель (bool vs. new class) даже не нужен.
@zvirja @aivascu, можем ли мы это пересмотреть? Я действительно не понимаю, почему в 2021 году асинхронные методы нельзя протестировать должным образом.
@Kralizek, если я правильно прочитал ситуацию, запрос не был отклонен, и есть даже PR, который это исправляет.
Я бегло просмотрел PR и должен сказать, что согласен с полученными отзывами.
Так что остается только либо реализовать обратную связь, либо подать новый PR с реализованной обратной связью.
Связанный PR в мобильном приложении не увидел 😅
Самый полезный комментарий
@ploeh В принципе, _any_
async
метод не работает без сбоев. Рассмотрим следующий пример:`` С #GuardedOpenGenericMethodReturningTaskResult(аргумент объекта)
общедоступная асинхронная задача
{
if (arg == null) выбросить новое исключение ArgumentNullException (nameof (arg));
}
`` ''
Этот метод не срабатывает, если вы вызываете его, будет
null
. Вместо этого возвращается неудачныйTask
. Следовательно, GuardClauseAssertion в его текущей форме не работает и жалуется на отсутствие защитного предложения.В реальном приложении почти весь код -
async
, поэтому каждый вызов -awaited
и немедленно выдается исключение. Так что совершенно нормально, что принцип «быстрого отказа» нарушается в том случае, если вы должныawait
Task, чтобы увидеть исключение.Конечно, вы можете как-то переписать код, чтобы он сразу же вышел из строя (создайте приватную функцию с ключевым словом
async
и переместите туда всю логику), но это не имеет практического смысла.