Как я могу обрабатывать асинхронные исключения с помощью System.Net.Http.HttpClient с моими интеграционными тестами?

Я запускаю набор интеграционных тестов, в которых используется System.Net.HttpClient. Большинство наших разделов «действия» в этих тестах используют этот общий формат:

// Arrange
// Do some stuff

// Act
var download = _client
    .GetStringAsync(testUrl)
    .Result;

// Assert
// Does "download" contain what I expected?

Однако периодический запуск этих тестов дает что-то вроде этого:

System.AggregateException : One or more errors occurred.
  ----> System.Threading.Tasks.TaskCanceledException : A task was canceled.
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task`1.get_Result()

Я понимаю, что использование HttpClient предназначено для асинхронного запуска и не идеально подходит для наших сценариев интеграционного тестирования, где мы всегда говорим ему подождать. Итак, это приводит меня к двум вопросам, которые в некоторой степени связаны:

  1. Является ли использование HttpWebRequest / HttpWebResponse более подходящим для этого сценария?
  2. Даже если это так, как лучше всего работать с HttpClient для обработки ошибок в запросах, запущенных асинхронно?

person Brandon Linton    schedule 22.05.2012    source источник
comment
Почему вы делаете это асинхронно для начала? Похоже, вы хотели бы сделать это синхронно... поэтому я бы сказал "да" на вопрос №1. Что касается вопроса № 2, я бы увеличил свойство Timeout класса HttpClient, если только вам не нужно проверять реакцию в течение определенного периода времени. В любом случае, я не уверен, почему асинхронность лучше подходит для модульного тестирования...   -  person Tom    schedule 23.05.2012
comment
Httpclient предоставляет только асинхронные методы. OP правильно преобразует их в синхронные вызовы, вызывая Result для задачи. это также, строго говоря, означает, что это не асинхронное исключение, а синхронное исключение, возникающее после блокировки в результате. я бы попробовал увеличить таймаут   -  person aL3891    schedule 31.07.2012


Ответы (2)


Как предположили предыдущие комментаторы, время вашего соединения, вероятно, истекло. Вы можете установить время ожидания с помощью _client.Timeout = timeoutInMilliseconds перед выполнением вызова GetStringAsync. Однако, если в настоящее время это значение по умолчанию (100 секунд), то я предполагаю, что удаленный сервер, с которым вы тестируете, фактически не работает, когда это происходит.

Дополнительную информацию о свойстве тайм-аута можно найти по адресу: http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

person Micah Zoltu    schedule 21.09.2013

System.AggregateException возникает из-за исключений, которые происходят в задаче, выполняемой синхронно. Использование асинхронных тестов позволяет исполнителю (в моем случае NUnit) декомпозировать задачу и получить настоящее исключение. Итак, приведенный выше код должен был выглядеть так:

[Test]
public async Task DownloadContainsWhatIExpected()
{
    // Arrange
    // Do some stuff

    // Act
    var download = await _client
        .GetStringAsync(testUrl);

    // Assert
    // Does "download" contain what I expected?
}

Использование async Task в сигнатуре метода, а затем await в асинхронных вызовах — лучший способ выполнить такого рода тесты.

person Brandon Linton    schedule 14.11.2014
comment
Абсолютно верно! Я просто предположил, что фреймворки модульного тестирования несовместимы с async/await, и я использовал .Wait() и .Result. Спасибо, что поставили меня на место! - person Skrymsli; 06.05.2015